Given an array of n elements, ordered in non-decreasing order, find the first and last occurrence of a number in an array. Since the array is sorted, the use of binary search is suggested. I used it to find the first entry, but I do not know how to change it to search for the last entry.
5 answers
Just use different behaviors when deciding which way to go, if you find a value equal to the desired. Java example:
int binarySearch(int[] a, int fromIndex, int toIndex, int key, boolean last) { int low = fromIndex; int high = toIndex - 1; while (low <= high) { int mid = (low + high) >>> 1; int midVal = a[mid]; if (midVal < key || (last && midVal == key)) low = mid + 1; else if (midVal > key || (!last && midVal == key)) high = mid - 1; } return last ? high : low; } - Something you have strange conditions to be honest. Why
|| (|| (needed? - pavel - @Alex Chermenin, do I understand correctly that fromIndex should be 0, and toIndex len (a) -1? - pinguin
- @ZvyagintsevDenis To bypass the entire array: fromIndex is 0, toIndex is equal to the length of the array. The code already has a decrease by one for the variable high. - Alex Chermenin
- @AlexChermenin And is checking for the existence of an element in an array to slow down the work of the algorithm? - pinguin
- You can not add a test for existence, simply if as a result, the index of the last entry was less than the index of the first - then there is no such element, and by indexes you can determine where to insert it so that the sorting does not get lost :) - Alex Chermenin
If your array is sorted (and this is a mandatory condition for binary search), then the same values are next to each other. Binary search you will find some of them (not necessarily the first or last), then you need to find the boundaries of the subarray (where the desired value borders on more or less), for which you can also use the binary search (so as not to look for brute force).
- oneAnd the complexity will suddenly become linear. And if an array of a million elements and there are such numbers - half a million - KoVadim
- @KoVadim, yes, I agree. Then it is necessary in both directions to look for the first non-coinciding element on the principle of binary search. - Voidificator
Use binary search, just look not for the number itself, but for the number + - epsilon, where epsilon is some small positive number, less difference between two different numbers is guaranteed. If this is an array of integers - epsilon can be equal to 0.5. Yes, you just need to understand that we will not find the numbers in this case, but the border is yes. This algorithm can be "slightly accelerated" if the upper limit is sought not from the beginning to the end, but from the lower limit to the end.
- 3perversion) in C ++ there are 2 versions of the search. In Java, I don’t know, but with their hands they differ exactly in 1 character (where <= or <). - pavel
- Yes, I thought about lower_bound and upper_bound, but judging by the question they want a general algorithm. - KoVadim
- @pavel, please explain - pinguin
- Here's another floating point is not enough, if the array of integers ... - 0andriy
If c ++, the std::equal_range does what is required.
In python, this is generally implemented in two lines:
lower_bound = my_list.index(10) upper_bound = len(my_list) - list(reversed(my_list)).index(10) - 1 More optimal option:
lower_bound = my_list.index(10) for k in range(lower_bound+1, len(my_list)+1): if my_list[k] != 10: break upper_bound = k - 1 number of repetitions: 10 000 000
list of 30 items
первый вариант: 16.31380480196094 второй вариант: 10.351039482047781 - and what complexity? - pinguin
.len,.index- O (1),.len- O (1),reversed- O (N). Where N is the length of the list. If I correctly counted, then O (N + 3) comes out - Yaroslav Surzhikov- @YaroslavSurzhikov in Java is also possible in a single line
IntStream.range(0, array.length).reduce(-1, (l, r) -> array[r] == key ? r : l);, but this is no longer a binary search :) - Alex Chermenin - @YaroslavSurzhikov, and exception handling (ValueError) slows down the algorithm? - pinguin
- @Zvyagintsev Denis yes, it slows down. At the expense of complexity, alas - I will not tell Check for entry into the list - O (N) - Yaroslav Surzhikov