Binary Search
Understand how binary search repeatedly eliminates half of a sorted array, its pointer-based implementation, and Big O complexity.
Binary Search
Binary search is a method for finding a target in a sorted array. Instead of examining every element, it repeatedly reduces the remaining search area by eliminating half of the array.
How it works
- Identify the middle element of the sorted array.
- Compare the target with that middle element.
- Use the comparison to eliminate half of the array.
- Repeat the process on the remaining half.
Each comparison makes the search area smaller. The essential relationship is:
Sorted array + middle-element comparison → half of the search area eliminated
Example of the process
Suppose the target is somewhere in a sorted array. Binary search first compares the target with the array’s middle element. After that comparison, one half is eliminated. The same process then continues with the remaining half: compare with its middle element, eliminate half again, and repeat.
Binary Search Implementation
Binary search uses three pointers to narrow the part of a sorted list that may contain a target value:
leftmarks the beginning of the current search range.rightmarks the end.middlemarks the position checked next.
At each step, compare the value at middle with the target. If the target is larger, move left past middle. If the target is smaller, move right before middle. If they are equal, return the result.
The function returns the index of the target if found. If the target is not present, it returns -1.
function binarySearch(array, target) {
let left = 0;
let right = array.length - 1;
while (left <= right) {
const middle = Math.floor((left + right) / 2);
if (array[middle] === target) {
return middle;
} else if (array[middle] < target) {
left = middle + 1;
} else {
right = middle - 1;
}
}
return -1;
}The loop continues while the search range is valid (left <= right). Each comparison removes part of that range by updating either left or right.
If the pointers cross without finding the target, no matching value remains in the search range and the function returns -1.
Examples
Basic usage
const numbers = [2, 5, 8, 12, 16, 23, 38, 56, 72, 91];
console.log(binarySearch(numbers, 23)); // 5
console.log(binarySearch(numbers, 2)); // 0
console.log(binarySearch(numbers, 50)); // -1 (not found)Essential pattern
- Initialize
leftto0andrighttoarray.length - 1. - Calculate
middle(Math.floor((left + right) / 2)or(left + right) // 2). - Compare the element at
middlewith the target. - Return the matching index, move
left, or moveright. - Return
-1when the search range is exhausted.
Binary Search and Big O
Binary search is analyzed by counting how the number of steps grows as the input size grows. Big O describes this growth, especially for larger inputs.
Three cases
| Case | Meaning | Binary search performance |
|---|---|---|
| Best case | The desired result is found immediately. | O(1) |
| Average case | The result requires a typical number of steps. | O(log n) |
| Worst case | The result takes the greatest number of steps, or the search finishes without finding it. | O(log n) |
Here, n represents the number of items being searched.
Why the growth is logarithmic
Binary search reduces the remaining search space by about half at each step. After one step, about half the items remain; after another step, about one quarter remain. Each additional step continues this halving process.
That is why doubling the input does not double the work. If an input has n items, an input with 2n items needs only about one additional step:
n items → about k steps
2n items → about k + 1 stepsThe extra step is enough because repeatedly halving 2n reaches the size of n after one additional halving. This slow growth is represented by O(log n).
Key Takeaways
- Requires Sorted Data: Binary search only works on arrays that are already sorted.
- Divide and Conquer: Each comparison with the middle element halves the remaining search area.
- Three Pointers: Employs
left,right, andmiddlepointers to iteratively shrink the search window untilleft > right. - Time Complexity: Best case is if the target is in the exact middle. Average and worst-case complexities are .
- Space Complexity: The iterative implementation operates in auxiliary space.
- Scalability: Because of logarithmic growth, doubling the input array size () adds only one additional step.