An efficient algorithm for finding an item from a sorted list of items. It works by repeatedly dividing in half the portion of the list that could contain the item, until you've narrowed down the possible locations to just one.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
{
"arr": "[2, 5, 8, 12, 16, 23, 38, 56, 72, 91]",
"target": 23,
"low": 0
}Overview
Binary Search finds a value in a sorted array by repeatedly halving the range that could contain it. It compares the target with the middle element: if they match, the search is over; if the target is larger, the left half (including the middle) can be thrown away; if smaller, the right half can.
Each comparison removes half of the remaining candidates, so even a billion-element array needs at most about 30 comparisons. The price is the precondition: the array must already be sorted, and the algorithm needs random access to jump straight to the middle.
In the default example the target is 23. The first middle is index 4 (value 16), so the search moves right; the next middle is index 7 (value 56), so it moves left; the third probe lands on index 5, which holds 23.
Step by step
- Set
low = 0andhigh = n - 1. - While
low <= high, computemid = floor((low + high) / 2). - If
arr[mid] === target, returnmid. - If
arr[mid] < target, setlow = mid + 1; otherwise sethigh = mid - 1. - If the loop ends, the target is not present; return
-1.
Complexity
| Case | Cost | Why |
|---|---|---|
| Best case | O(1) | The first middle element is the target. |
| Average case | O(log n) | The range halves on every comparison. |
| Worst case | O(log n) | At most floor(log2 n) + 1 comparisons. |
| Extra space | O(1) | Iterative version; the recursive one uses O(log n) stack. |
When to use it
- Any repeated lookup in sorted, randomly accessible data.
- 'Binary search on the answer' problems: finding the smallest value that satisfies a monotonic condition, such as the minimum capacity to ship packages in D days.
- Finding insertion points, first/last occurrences, and boundaries (lower_bound / upper_bound).
Common mistakes
low < highversuslow <= highandmid - 1versusmid: mixing conventions causes infinite loops or skipped elements. Pick one invariant and stick to it.(low + high) / 2overflows in fixed-width integer languages; uselow + (high - low) / 2.- Running it on unsorted data gives wrong answers silently rather than failing.
A dry run is the best way to check your understanding of Binary Search: follow each row, predict the next one, and compare. The run below takes 16 steps in total. Steps that only re-print loop counters are left out so the decisions stand out. The Line column refers to the line numbers in the code listing above.
- Input
- 2,5,8,12,16,23,38,56,72,91
- Target
- 23
- Result
- return value = 5
| Step | Line | Array | What happens |
|---|---|---|---|
| 1 | 2 | [2, 5, 8, 12, 16, 23, 38, 56, 72, 91] | target = 23, low = 0 |
| 3 | 4 | [2, 5, 8, 12, 16, 23, 38, 56, 72, 91] | low = 0, high = 9, condition = 0 <= 9 |
| 5 | 6 | [2, 5, 8, 12, 16, 23, 38, 56, 72, 91] | low = 0, high = 9, mid = 4, arr[mid] = 16, target = 23, condition = 16 === 23 |
| 6 | 8 | [2, 5, 8, 12, 16, 23, 38, 56, 72, 91] | low = 0, high = 9, mid = 4, arr[mid] = 16, target = 23, condition = 16 < 23 |
| 8 | 4 | [2, 5, 8, 12, 16, 23, 38, 56, 72, 91] | low = 5, high = 9, condition = 5 <= 9 |
| 10 | 6 | [2, 5, 8, 12, 16, 23, 38, 56, 72, 91] | low = 5, high = 9, mid = 7, arr[mid] = 56, target = 23, condition = 56 === 23 |
| 11 | 8 | [2, 5, 8, 12, 16, 23, 38, 56, 72, 91] | low = 5, high = 9, mid = 7, arr[mid] = 56, target = 23, condition = 56 < 23 |
| 13 | 4 | [2, 5, 8, 12, 16, 23, 38, 56, 72, 91] | low = 5, high = 6, condition = 5 <= 6 |
| 15 | 6 | [2, 5, 8, 12, 16, 23, 38, 56, 72, 91] | low = 5, high = 6, mid = 5, arr[mid] = 23, target = 23, condition = 23 === 23 |
| 16 | 7 | [2, 5, 8, 12, 16, 23, 38, 56, 72, 91] | return value = 5 |