Searching · 02 / 19
Binary search visualization
Binary search finds a target in a sorted array by repeatedly halving the range that can still contain it.
Time: best case O(1), worst case O(log n). Space: O(1). What Big-O notation means.
Last updated
About this lesson
- Concept it teaches
- Range invariant, O(log n)
- Canonical source
- Knuth, TAOCP vol. 3, section 6.2.1
- Builds on
- Linear search
- Concept it teaches
- Range invariant, O(log n)
- Canonical source
- Knuth, TAOCP vol. 3, section 6.2.1
- Builds on
- Linear search
I already know this: go to the check
See
+10 XP
Watch the real code run, one step at a time. Change the input and see what happens.
Predict first. Before you press Play, guess what the first comparison will be.
Run Binary search
- Comparisons
- 0
- Step
- 1/8
- Current
- Comparing
- Done
- Ruled out
Array. index 0: 2; index 1: 5; index 2: 8; index 3: 12; index 4: 16; index 5: 23; index 6: 38.
The target can be anywhere in indexes 0 to 6.
The target can be anywhere in indexes 0 to 6.
Step 1/8comparisonwrite
With focus on the player: Space play · ← → step · Home End jump
Understand
+15 XP
The idea in plain words: why it works, what it costs, when to use it. One question at the end.
Binary search finds a value in a sorted array by comparing the target with the middle element and discarding half of the remaining range in every round. It needs about log₂ n rounds instead of the n comparisons that a scan needs.
How it works
- Keep a range
lotohithat can still contain the target. At first it covers the whole array. - Look at the middle index,
mid. - If
array[mid]equals the target, returnmid. - If
array[mid]is smaller than the target, the target can only be to the right: setlo = mid + 1. - Otherwise it can only be to the left: set
hi = mid - 1. - Repeat while
lo <= hi. When the range is empty, return-1.
A worked example of binary search
Search for 21 in the sorted array [3, 8, 12, 17, 21, 26, 34]:
lo = 0,hi = 6,mid = 3, value 17. 17 is less than 21, so setlo = 4.lo = 4,hi = 6,mid = 5, value 26. 26 is greater than 21, so sethi = 4.lo = 4,hi = 4,mid = 4, value 21. 21 equals 21: return 4.
The result is 4, found in 3 rounds and 5 comparisons (this lesson counts "is it equal?" and "is it less?" as separate comparisons). A linear scan would also need 5 comparisons for this target, so there is no gain on 7 elements. The gap opens as the array grows.
Now search for 10, which is missing:
lo = 0,hi = 6,mid = 3, value 17. 17 is greater than 10, so sethi = 2.lo = 0,hi = 2,mid = 1, value 8. 8 is less than 10, so setlo = 2.lo = 2,hi = 2,mid = 2, value 12. 12 is greater than 10, so sethi = 1.
After round 3 the range is empty, so the result is -1.
Binary search pseudocode
Indexes start at 0, as in the code of this lesson, and A is sorted in ascending order.
BINARY-SEARCH(A, n, target)
1 lo = 0
2 hi = n - 1
3 while lo <= hi
4 mid = floor((lo + hi) / 2)
5 if A[mid] == target
6 return mid
7 if A[mid] < target
8 lo = mid + 1
9 else hi = mid - 1
10 return -1
Each round removes the middle element and one side of it. In a language with fixed-width integers, write line 4 as mid = lo + floor((hi - lo) / 2), because lo + hi can overflow: a bug of exactly this kind was reported in Java's library implementation in 2006. JavaScript numbers do not overflow at these sizes, so the lesson uses the simpler form.
Time and space complexity
Every comparison halves the range. An array of 1,000 elements needs at most 10 rounds, and an array of 1,000,000 needs at most 20. Doubling the array adds only one more round.
| Best case time | O(1) |
|---|---|
| Average case time | O(log n) |
| Worst case time | O(log n) |
| Extra space | O(1) |
- Best, O(1): the target is exactly the first middle element.
- Average, O(log n): the range is halved on each round until it holds one element or none.
- Worst, O(log n): the target is missing or found on the last round, after about
log₂ nhalvings. - Space, O(1): the iterative version only keeps
lo,hiandmid.
When to use it, and when not to
- Use it when the data is already sorted, or will be searched many times, so the cost of sorting (
O(n log n)) is paid once. - It needs random access to any index. A linked list does not qualify, because reaching the middle costs
O(n). - On unsorted data it is wrong, not just slow: the argument "bigger than the middle means it is to the right" only holds when the array is sorted, so it can return
-1for a value that is really there. Use linear search instead.
Where binary search is used
- Standard libraries. Java's
Arrays.binarySearch, C++'sstd::binary_searchandstd::lower_bound, and Python'sbisectmodule all halve a sorted range.bisectis also the usual way to find where a new value belongs in a list that must stay sorted. - Database indexes. A B-tree index keeps its keys in sorted order inside each page, so once the tree has led to the right page, the database finds the key in it by halving the sorted keys. This is why an indexed lookup in a table of millions of rows touches only a handful of pages.
- Finding a bug with
git bisect. The commits are in order, and the question "does the bug appear here?" changes from no to yes only once.git bisecttests the middle commit and discards half of the range, so about 10 tests are enough for 1,000 commits.
Common mistake and edge cases
Related algorithms and variations
The lower-bound and upper-bound versions return the first or the last position of a value, which fixes the duplicates caveat above. Interpolation search guesses the position from the values themselves: on evenly spread keys it needs about log log n comparisons, but its worst case is O(n) (Knuth treats it in section 6.2.1). A binary search tree keeps the same left-or-right decisions in a structure that also accepts inserts.
The opposite trade is linear search, which needs no sorting, and linear search vs binary search compares the two on the same inputs. To get a sorted array in the first place, see merge sort.
One question to finish
What must be true about the array for binary search to work?
Predict
+20 XP
The run stops and asks what happens next. The real run says if you were right.
Practice
+30 XP
Order the lines, fill in the gap, trace it by hand. The real run corrects every answer.
Check yourself
Four questions from memory. They also join your daily review. Questions return on a spaced schedule: right answers come back later, misses come back tomorrow.