How do you implement binary search, and what are the common bugs?
On a sorted array, keep two pointers low and high, check the middle element, and throw away the half that cannot contain the target. Repeat until found or low passes high. It runs in O(log n). The classic bugs are computing mid as (low + high) / 2, which can overflow in Java or C++, and off-by-one errors in the loop condition and pointer updates.
Explain it simply
Think of finding a word in a printed dictionary. You do not start at page 1. You open somewhere in the middle, see that your word comes later, and ignore the whole first half. Then you open the middle of what is left, and so on. Each step throws away half the remaining pages, so even a 1,000-page dictionary needs only about 10 steps.
Binary search does exactly this on a sorted array. If the array is not sorted, the "throw away half" step is not safe, and the method does not work.
Line by line
function binarySearch(arr, target) {
let low = 0;
let high = arr.length - 1; // inclusive: high is a valid index
while (low <= high) { // <= so a one-element range is still checked
const mid = low + Math.floor((high - low) / 2); // overflow-safe middle
if (arr[mid] === target) {
return mid; // found it
} else if (arr[mid] < target) {
low = mid + 1; // target is to the right; mid is already ruled out
} else {
high = mid - 1; // target is to the left; mid is already ruled out
}
}
return -1; // low crossed high, target is not present
}
const nums = [2, 5, 8, 12, 16, 23, 38, 56, 72, 91];
console.log(binarySearch(nums, 23)); // Output: 5
console.log(binarySearch(nums, 2)); // Output: 0
console.log(binarySearch(nums, 91)); // Output: 9
console.log(binarySearch(nums, 7)); // Output: -1
console.log(binarySearch([], 4)); // Output: -1Tracing the search for 23:
- low = 0, high = 9, mid = 4, arr[4] = 16 < 23, so low = 5.
- low = 5, high = 9, mid = 7, arr[7] = 56 > 23, so high = 6.
- low = 5, high = 6, mid = 5, arr[5] = 23. Found at index 5.
Three comparisons instead of six for a linear scan, and the gap grows quickly with bigger arrays.
How it works
The loop keeps one promise, called the invariant: if the target is in the array, it is somewhere between low and high, inclusive. Every update keeps that promise true while shrinking the range. When low > high, the range is empty, so the target is not there.
Why the overflow-safe mid? In Java, C++ or C, low and high are 32-bit integers. If both are above about 1.07 billion, low + high exceeds the largest int (2,147,483,647) and wraps around to a negative number, giving a negative index. low + (high - low) / 2 gives the same middle without ever adding two large numbers. JavaScript numbers do not overflow at this size, but interviewers expect you to write it this way anyway.
int mid = low + (high - low) / 2; // safe
// int mid = (low + high) / 2; // can overflow for very large arraysComplexity
| Case | Time | Extra space |
|---|---|---|
| Iterative (above) | O(log n) | O(1) |
| Recursive version | O(log n) | O(log n) call stack |
| Linear search, for comparison | O(n) | O(1) |
For an array of 10 lakh (1,000,000) elements, binary search needs at most 20 comparisons, because 2^20 is just over a million.
Common mistakes
- Using
low < highwith an inclusivehigh. When the range shrinks to one element, the loop stops without checking it. - Writing
low = midorhigh = mid. If mid is already ruled out and you do not move past it, the range can stop shrinking and the loop runs forever. (low + high) / 2in Java or C++, which overflows for huge arrays.- Forgetting
Math.floorin JavaScript, which gives a fractional index like 4.5. - Running it on unsorted data.
- Mixing the two styles: inclusive
high = n - 1goes withlow <= highandhigh = mid - 1; exclusivehigh = ngoes withlow < highandhigh = mid. Pick one and stay consistent.
What to say in the interview
"Binary search works on sorted data. I keep low and high as an inclusive range where the target must be. While low is less than or equal to high, I compute mid as low plus half of high minus low, which avoids integer overflow. If the middle element is the target, I return it; if it is smaller, I move low to mid plus 1; otherwise I move high to mid minus 1. If the loop ends, the target is absent. It is O(log n) time and O(1) space."
Follow-up questions
- How do you find the first or last occurrence of a value that appears many times?
- How do you search in a rotated sorted array?
- How would you find the square root of a number using binary search?
- What is "binary search on the answer"?
Go deeper
Read these once the basics above feel easy.
To find the first occurrence of a target in an array with duplicates, do not return when you find a match. Record the index and keep searching left with high = mid - 1. For the last occurrence, record and search right with low = mid + 1. Both stay O(log n).
Binary search on the answer applies whenever a yes/no condition flips only once over a range of possible answers. For example, "what is the minimum capacity of a truck to ship all parcels in D days?" Capacity is the search range, and "can we ship in D days with this capacity?" is the check.