Binary Search In Detail
I hope we all have some idea about what binary search is and does. But I’m not going to explain the algorithm step by step, rather I’m going to give an insight into how binary search works and can be used.
Check out: geeksforgeeks.org/binary-search if you’re unaware of Binary Search.
Given a sorted array, we find the middle-most element and check the element with the key. If the middle-most element is equal to key, we’ve found the key. If the middle-most element is greater than the key, we search on the left half of the middle-most element, else we search on the right half.
Here’s an iterative code for Binary Search in Java
Notice that in line 6, we use
int mid = (low + high) / 2;
But calculating mid this way is ineffective. Why? Let’s take an example.
Let us take integers from an integer low to an integer high (both included).
Notice the mids computed by formulae in 3rd and 4th columns.
- for low = 3 and high = 11, the number of elements (#elements) = 9
So there is only 1 mid, i.e., 7
* Both formulae have computed the mid correctly - for low = 3 and high = 10, #elements = 8
So there are 2 mids, 6 (lower mid) and 7 (higher mid)
* Both formulae have computed the lower mid correctly - for low = -11 and high = -3, #elements = 9
So there is only 1 mid, i.e., -7
* Both formulae have computed the mid correctly - for low = -10 and high = -3, #elements = 8
So there are 2 mids, -7 (lower mid) and -8 (higher mid)
* The formula(low + high) / 2
has failed to compute the lower mid correctly but the other formula has computed it correctly.
So, we should always use the below formula to compute lower mid as it is much more reliable:
int mid = low + ((high - low)/2);
When #elements = odd, we have only 1 mid. So we can use the above formula to compute mid.
When #elements = even, the above formula only gives the lower mid.
The higher mid can be computed by the below formula:
int mid2 = low + ((high - low + 1) / 2);
Now, the interesting part…
Let’s go back to the iterative code for Binary Search. Notice three things.
1. How we are moving low and high
2. How we are computing mid
3. The condition in while loop
The beauty of Binary Search lies in these three things alone. Let us explore this further.
For a simple binary search where we just have to find the element in the array,
we use the following:
1. low = mid - 1
for moving low
2. high = mid + 1
for moving high
3. mid = low + ((high - low) / 2)
(why? discussed above)
4. low <= high
in the while loop
Is it always the case that we use the same conditions for binary search?
It depends…on our problem statement.
Example #1:
Given an integer x, find the maximum element y in an array of size N that satisfies the condition y <= x
Solution:
We know that x might not be in the array. So the simple binary search for x in the given array won’t work. But for binary search, all we know is x, the key. We need to find the element in the array that’s the closest to x and less than or equal to x (if it exists).
Three things should always come to your mind when using binary search:
1. How should we move low and high?
2. How should we compute mid?
3. What would be the condition in while loop?
We always start with ‘How to move low and high?’ and then find out how to compute mid and what might be the while condition. NOT the other way round.
- How to move low and high?
Whenarray[mid] < x
, there is a possibility that the current element might be the answer (since y can be less than x).
So, we shouldn’t discard mid while moving low.
Hence, low becomeslow = mid
, notlow = mid + 1
High remains the same as it is irrelevant to our problem statement. - How to compute mid?
When we usemid = low + ((high - low) / 2)
, we are calculating the lower mid. So when the #elements in the array is even, theif(array[mid] > x)
becomes false, so control will go to else clause wherelow = mid
. This results in an infinite loop. (why? take an example)
Hence, we take the higher mid, i.e.,mid = low + ((high - low + 1) / 2)
- What would be the condition in while loop?
Since we are storing the maximum element that is less than or equal to x in low, we should stop when low = high and returnarray[low]
orarray[high]
. Hence, the condition in while loop islow < high
.
The Solution in Java looks like this:
Example #2:
Given an integer x, find the minimum element y in an array of size N that satisfies the condition y >= x
Solution:
Using a similar analytical approach we used in example 1 (try it out yourself), we can say that
low = mid + 1
for moving lowhigh = mid
for moving highmid = low + ((high - low) / 2)
for calculating midlow < high
for the condition in while loop
Hence we can tabulate different scenarios of using Binary Search as follows:
Feel free to experiment with these conditions and I hope you have gotten some insight into how to use binary search.
Namaste!