Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between basic binary search for upper bound and lower bound?

In the article http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=binarySearch, the author discusses binary search. He makes a distinction between finding the lowest value where something is true, and the highest value where something is false. The array being searched looks something like:

false false false true true

I am curious as to why these two cases are different. Why can't you just find the lowest value which is true, then subtract one to find the highest value which is false?

Edit2: Ok, so I understand lower vs upper bound. Now, I am struggling to understand, when searching for the smallest integer greater than or equal to the query, why we can't just change the if(mid>query) to if(mid>=query) and have it do lower instead of upper bound.

Edit: Here is what the article stated:

"Now we finally get to the code which implements binary search as described in this and the previous section:

binary_search(lo, hi, p):
   while lo < hi:
      mid = lo + (hi-lo)/2
      if p(mid) == true:
         hi = mid
      else:
         lo = mid+1

   if p(lo) == false:
      complain                // p(x) is false for all x in S!

   return lo         // lo is the least x for which p(x) is true

...

If we wanted to find the last x for which p(x) is false, we would devise (using a similar rationale as above) something like:

binary_search(lo, hi, p):
   while lo < hi:
      mid = lo + (hi-lo+1)/2    // note: division truncates
      if p(mid) == true:
         hi = mid-1
      else:
         lo = mid

   if p(lo) == true:
      complain                // p(x) is true for all x in S!

   return lo         // lo is the greatest x for which p(x) is false

."

like image 649
John Targaryen Avatar asked Feb 08 '15 00:02

John Targaryen


People also ask

What is upper bound and lower bound binary search?

The lower and upper bound of a binary search are the lowest and highest position where the value could be inserted without breaking the ordering.

How do you find the upper bound and lower bound?

In order to find the upper and lower bounds of a rounded number: Identify the place value of the degree of accuracy stated. Divide this place value by 2 . Add this amount to the given value to find the upper bound, subtract this amount from the given value to find the lower bound.

How do you find the upper bound and lower bound in Java?

You can calculate the lower bound : lb = Math. abs(-10) - 2 = 8, that is the last index of the array, but there is no upper bound, because 22 is already biggest element in the array and there is no element at position 9. Equal range of number 6 is empty, because there is no number 6 in the array.

Does Lowerbound use binary search?

Binary Search functions in C++ STL (binary_search, lower_bound and upper_bound) Binary search is an important component in competitive programming or any algorithmic competition, having knowledge of shorthand functions reduces the time to code them. This searching only works when container is sorted.


1 Answers

The lower and upper bound of a binary search are the lowest and highest position where the value could be inserted without breaking the ordering. (In the C++ standard library, these bounds will be represented by iterators referencing the element before which the value could be inserted, but the concept is not essentially changed.)

Take, for example, a sorted range

1 2 3 4 5 5 5 6 7 9

In a binary search for 3, we will have

   v-- lower bound
1 2 3 4 5 5 5 6 7 9
     ^-- upper bound

And in a binary search for 5:

       v-- lower bound
1 2 3 4 5 5 5 6 7 9
             ^-- upper bound

The lower and upper bound are the same if the element does not exist in the range. In a binary search for 8:

                 v-- lower bound
1 2 3 4 5 5 5 6 7 9
                 ^-- upper bound

The author of the article to which you refer phrases all this in the equivalent terms of "smaller than" and "greater than" so that in a search of 5,

       v-- lower bound
t t t t f f f f f f      <-- smaller than?
1 2 3 4 5 5 5 6 7 9
f f f f f f f t t t      <-- greater than?
             ^-- upper bound

The C++ iterators will, in all these cases, refer to the element directly behind the bound. That is to say:

  • In the search for 3, the iterator returned by std::lower_bound would refer to 3 and the one from std::upper_bound would refer to 4
  • In the search for 5, the iterator returned by std::lower_bound would refer to the first 5 and the one from std::upper_bound would refer to 6
  • In the search for 8, both would refer to 9

This is because the convention in the C++ standard library for insertions is to pass an iterator referring to the element before which the new element should be inserted. For example, after

std::vector<int> vec { 1, 3, 4, 5, 5, 5, 6, 7, 9 };
vec.insert(vec.begin() + 1, 2);

vec would contain 1, 2, 3, 4, 5, 5, 5, 6, 7, 9. std::lower_bound and std::upper_bound follow this convention so that

vec.insert(std::lower_bound(vec.begin(), vec.end(), 5), 5);
vec.insert(std::upper_bound(vec.begin(), vec.end(), 8), 8);

work as desired and leave vec sorted.

More generally, this is an expression of the way ranges are specified in the C++ standard library. The beginning iterator of a range refers to the first element of the range (if any), while the ending iterator refers to the element (if any) directly behind the end of the range. Another way to look at it is that the iterators returned by std::lower_bound and std::upper_bound span the range of elements in the searched range that are equivalent to the searched element.

This range is empty if the element is not in the range, so that lower_bound and upper_bound return the same iterator, and otherwise lower_bound returns an iterator referring to the first element in the searched range that's equivalent to the search value while upper_bound returns an iterator referring to the element (if any) that's directly behind the last such element.

like image 66
Wintermute Avatar answered Sep 24 '22 07:09

Wintermute