Binary Search and duplicates - search

Let's say we an array {–2, 8, 13, 22, 25, 25, 38, 42, 51, 103}
When a binary search splits it in 2 the first time, what will be considered the middle value?
My own guess is the second value named 25, because only then the search knows that it's identical.

I believe it always tries to find the middle by
(0+n)/2 = (0+9)/2 = 4(Integer)
In your case.
So in case you want to search 25 itself, as per the algorithm you will find in the lower bound group, position 4 first as a match.

The middle value is first 25 number.
Your binarySearch first call is something like that : binarySearch(a,1,a.length) , where "a" is your array.
Your array length is 10 , so m = ((10-1) +1)/2 = 5 position in array .
Then you call binarySearch(1,m) and apply the same method to this array (the first half from orginal array )
–2, 8, 13, 22, 25

Related

In the case of a tie, how do I return the largest and most frequent number in python?

I have a list of numbers. I created this frequency dictionary d:
from collections import Counter
mylist = [10, 8, 12, 7, 8, 8, 6, 4, 10, 12, 10, 12]
d = Counter(mylist)
print(d)
The output is like this:
Counter({10: 3, 8: 3, 12: 3, 7: 1, 6: 1, 4: 1})
I know I can use max(d, key=d.get) to get value if there is no tie in frequency. If multiple items are maximal, the function usually returns the first one encountered. How can I return the largest number, in this case, 12, instead of 10? Thank you for your help!
Define a lambda function that returns a tuple. Tuples are sorted by their first value, and then tie-broken by subsequent values. Like this:
max(d, key=lambda x:(d.get(x), x))
So for the two example values, the lambda will return (3, 10) and (3, 12). And of course, the second will be considered the max.
Further explanation:
When the max function is given a collection to find the max of, and a key, it will go over the values in the collection, passing each value into the key function. Whatever element from the collection results in the maximal output from the key function is considered the maximal value.
In this case, we're giving it a lambda function. Lambdas are just functions. Literally no difference in their usage, just a different syntax for defining them. The above example could have been written as:
def maxKey(x):return (d.get(x), x)
max(d, key=maxKey)
and it would behave the same way.
Using that function, we can see the return values that it would give for your sample data.
maxKey(10) #(3, 10)
maxKey(12) #(3, 12)
The main difference between the anonymous lambda above and using d.get is that the lambda returns a tuple with two values in it.
When max encounters a tie, it returns the first one it saw. But because we're now returning tuples, and because we know that the second value in each tuple is unique (because it comes from a dictionary), we can be sure that there won't be any duplicates. When max encounters a tuple it first compares the first value in the tuple against whatever it has already found to be the maximal value. If there's a tie there, it compares the next value. If there's a tie there, the next value, etc. So when max compares (3, 10) with (3, 12) it will see that (3, 12) is the maximal value. Since that is the value that resulted from 12 going into the key function, max will see 12 as the maximal value.
You can get the max count (using d.most_common), and then get the max of all keys that have the max count:
max_cnt = d.most_common(1)[0][1]
grt_max = max(n for n, cnt in d.items() if cnt == max_cnt)
print(grt_max)
Output:
12

create list from list where values only increase by 1

I have the code below that gets the maximum value from a list. It then compares it to the maximum value of the remaining values in the list, and if it is more than 1 higher than the next greatest value, it replaces the original list maximum with 1 higher than the next greatest value. I would like the code to search the entire list and make sure that any value in the list is at most 1 larger than any other value in the list. I know this ins’t the best worded explanation, I hope the example lists below make what I’m trying to accomplish clearer.
for example I don’t want to get a final list like:
[0,2,0,3]
I would want the final list to be
[0,1,0,2]
input:
empt=[0,2,0,0]
Code:
nwEmpt=[i for i in empt if i !=max(empt)]
nwEmpt2=[]
for i in range(0,len(empt)):
if (empt[i]==max(empt))&(max(empt)>(max(nwEmpt)+1)):
nwEmpt2.append((max(nwEmpt)+1))
elif (empt[i]==max(empt))&(max(empt)==(max(nwEmpt)+1)):
nwEmpt2.append(max(empt))
else:
nwEmpt2.append(empt[i])
output:
nwEmpt2
[0,1,0,0]
min_value = min(empt)
empt_set = set(empt)
for i in empt:
nwEmpt.append(min_value + len(list(filter(lambda x: x < i, empt_set))))
This gives e.g. for input empt = [8, 10, 6, 4, 4] output nwEmpt = [6, 7, 5, 4, 4].
It works by mapping each element to (the minimum value) + (the number of distinct values smaller than element).

Remove number from list in which difference between two number are less then specific number

a = [2, 5, 6, 12, 21, 25, 32, 41]
This is my list and I want to remove all the numbers which are not in difference of 7.
Before diving into the answers, let's go over what we're dealing with.
You got a list 'A', which you need to loop through to get a list of numbers that are greater than the previous value + 7
If you boil down the question, you get left with two main goals
We need a loop
and we have a list with the final answer
There are two generic ways of approaching this question. In a loop, we populate a new list. The second way is to manipulate the original list.
Although the First approach requires additional memory, I'll be using the First approach for simplicity.
a = [2, 5, 6, 12, 21, 25, 32, 41] # your original list
b = [] # Empty list that will contain final product
for i in range(len(a)):
if len(b) == 0: # if the list is empty, we add first item from 'a' (In our example, it'll be 2)
b.append(a[i])
else:
if a[i] > b[len(b)-1]+7 or a[i] < b[len(b)-1]-7: # for every value of a, we compare the last digit from list b
b.append(a[i])
As far as I have understood your question, in your output list, only those elements should be there whose sum is 7. So that can be achieved by
i=1;
while i<len(a):
if(a[i]-a[i-1] < 7):
a.remove(a[i])
else:
i+=1
print(a)

Reverse exercise (Python Codecademy course, part "Practice makes perfect" 15/15)

the task runs as follows:
Define a function called reverse that takes a string textand returns that string in reverse.You may not use reversed or [::-1] to help you with this.
My code works all right but I want to understand one detail. Tks to all.
def reverse (text):
result = ''
for i in range (len(text)-1,-1,-1):
result += text[i]
return result
The point is that originally I wrote in the 3rd line for i in range (len(text)-1,0,-1):But the program returned '!nohty' instead of '!nohtyP'. So I changed to (len(text)-1,-1,-1) ant it's ok.
BUT WHY?!
The end point is omitted from the range.
>>> range(2,5)
[2, 3, 4]
To get the zeroth element, you need -1.
Because the text (Python!) is of 7 length and lists are zero based (starting from 0) and the for loop is decreasing, you need to have -1.
The string "Python!" is 7 characters. Range is exclusive with the final number, thus the range is accounting for 6, 5, 4, 3, 2, 1, 0.
The length - 1 = 6, range of 6 to -1, where -1 is exclusive accounts for numbers 0 - 6. Because lists are 0 based, it accounts for all. With zero as the range's second argument, you only get the numbers 6, 5, 4, 3, 2, 1, which doesn't account for the whole word.
For example:
The word "Stack" has 5 letters.
Once it is a list, it occupies the indices 0, 1, 2, 3, 4.
You are looping through the whole word, thus you need to access the 0th element. To do that, the range must go to -1 exclusive.
For your loop:
>>> range(6, -1, -1)
[6, 5, 4, 3, 2, 1, 0]
Then, when you access it by doing:
text = "Python!"
for i in range(len(text)-1, -1, -1):
print(text[i])
text[i] accesses all the individual characters and prints them, backwards.

Need help ordering numbers in Python(Ascending Order)

I'm fairly new to coding and just started this week. I'm attempting to order numbers such as test grades in ascending order. I've tried it and here's what I have (below) - it doesn't sort the list. What am I missing? I'm using Pyscripter to code python.
li=['75, 95, 65, 100, 10']
li.sort()
print(li)
li=['75,95,65,100,10'] reads one string only.
Either use
li=['75','95','65','100','10'] (list of strings)
or li=[75,95,65,100,10] (list of ints). That should work.
li=[75, 95, 65, 100, 10]
for i in range(len(li)):
for x in range (i+1, len(li)):
if li[i] > li[x]:
li[x], li[i] = li[i], li[x]
print(li)
I modified the list by removing the ' ' inside the li=[] because you have int numbers and not strings, if you want to understand much easy Python I recommend to start with the basic loops and not with predefined functions like sort().
li=[75, 95, 65, 100, 10]
li.sort(key=int)# ascending order.
For descending order add:
li.sort(key=int, reverse=True )
print (li)

Resources