Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find the first element in a sorted array that is greater than the target

In a general binary search, we are looking for a value which appears in the array. Sometimes, however, we need to find the first element which is either greater or less than a target.

Here is my ugly, incomplete solution:

// Assume all elements are positive, i.e., greater than zero int bs (int[] a, int t) {   int s = 0, e = a.length;   int firstlarge = 1 << 30;   int firstlargeindex = -1;   while (s < e) {     int m = (s + e) / 2;     if (a[m] > t) {       // how can I know a[m] is the first larger than       if(a[m] < firstlarge) {         firstlarge = a[m];         firstlargeindex = m;       }       e = m - 1;      } else if (a[m] < /* something */) {       // go to the right part       // how can i know is the first less than       }   } } 

Is there a more elegant solution for this kind of problem?

like image 537
SecureFish Avatar asked Jul 01 '11 22:07

SecureFish


People also ask

How do you find the first occurrence of an element in an array?

The idea to solve this problem is iterate on the elements of given array and check given elements in an array and keep track of first and last occurrence of the found element's index. Below are the steps to implement the above idea: Run a for loop and for i = 0 to n-1. Take first = -1 and last = -1.

How do you find the number of elements greater smaller than an element in an array?

The simplest trick is sort the array first and count the number of elements in the array. So for example if you have 10 elements then your first element is less than 9 and likewise the second element is smaller than 8 and so on.

How do I find the first and last elements of an array?

The first and last elements are accessed using an index and the first value is accessed using index 0 and the last element can be accessed through length property which has one more value than the highest array index. The array length property in JavaScript is used to set or return the number of elements in an array.


1 Answers

One way of thinking about this problem is to think about doing a binary search over a transformed version of the array, where the array has been modified by applying the function

f(x) = 1 if x > target        0 else 

Now, the goal is to find the very first place that this function takes on the value 1. We can do that using a binary search as follows:

int low = 0, high = numElems; // numElems is the size of the array i.e arr.size()  while (low != high) {     int mid = (low + high) / 2; // Or a fancy way to avoid int overflow     if (arr[mid] <= target) {         /* This index, and everything below it, must not be the first element          * greater than what we're looking for because this element is no greater          * than the element.          */         low = mid + 1;     }     else {         /* This element is at least as large as the element, so anything after it can't          * be the first element that's at least as large.          */         high = mid;     } } /* Now, low and high both point to the element in question. */ 

To see that this algorithm is correct, consider each comparison being made. If we find an element that's no greater than the target element, then it and everything below it can't possibly match, so there's no need to search that region. We can recursively search the right half. If we find an element that is larger than the element in question, then anything after it must also be larger, so they can't be the first element that's bigger and so we don't need to search them. The middle element is thus the last possible place it could be.

Note that on each iteration we drop off at least half the remaining elements from consideration. If the top branch executes, then the elements in the range [low, (low + high) / 2] are all discarded, causing us to lose floor((low + high) / 2) - low + 1 >= (low + high) / 2 - low = (high - low) / 2 elements.

If the bottom branch executes, then the elements in the range [(low + high) / 2 + 1, high] are all discarded. This loses us high - floor(low + high) / 2 + 1 >= high - (low + high) / 2 = (high - low) / 2 elements.

Consequently, we'll end up finding the first element greater than the target in O(lg n) iterations of this process.

Here's a trace of the algorithm running on the array 0 0 1 1 1 1.

Initially, we have

0 0 1 1 1 1 L = 0       H = 6 

So we compute mid = (0 + 6) / 2 = 3, so we inspect the element at position 3, which has value 1. Since 1 > 0, we set high = mid = 3. We now have

0 0 1 L     H 

We compute mid = (0 + 3) / 2 = 1, so we inspect element 1. Since this has value 0 <= 0, we set mid = low + 1 = 2. We're now left with L = 2 and H = 3:

0 0 1     L H 

Now, we compute mid = (2 + 3) / 2 = 2. The element at index 2 is 1, and since 10, we set H = mid = 2, at which point we stop, and indeed we're looking at the first element greater than 0.

like image 58
templatetypedef Avatar answered Sep 24 '22 14:09

templatetypedef