Binary Search Pattern
Learn to recognize when a search space is monotonic — so checking the midpoint tells you which half to discard — and how to avoid the classic off-by-one bugs.
0/5 practice problems solved
Recognizing the pattern
Reach for it when you need to
- the input is sorted, or the answer space is monotonic ("if x works, does x+1 also work?");
- you're asked for a specific value, an insertion point, or a boundary (first/last true, minimum satisfying value);
- a rotated or partially-sorted array still has one half that's fully ordered;
- the brute force is an O(n) linear scan but the search space can be halved every step (O(log n)).
Don't use it when
- The data has no monotonic property to exploit — sorting it first may cost more than it saves.
- You need every matching element, not just one boundary — a linear scan or two pointers may be simpler.
- The 'answer space' framing doesn't have a clean true/false split at every candidate value.
- The array is small and unsorted one-off — the overhead of proving monotonicity isn't worth it.
Core mental model
Maintain a search range [lo, hi] where the answer is guaranteed to still be inside it. Check the midpoint: its result tells you, with certainty, which half cannot contain the answer, so you discard that half in one step. The loop invariant — 'the answer, if it exists, is in [lo, hi]' — must hold before and after every iteration, which is what makes halving safe.
Visual trace
Search for 9 in [1, 3, 5, 7, 9, 11, 13]. Each step halves the range that could still contain the target.
Worked example: Binary Search
nums = [1, 3, 5, 7, 9, 11, 13], target = 9. Halve the range until it converges on the target.
| lo / hi | mid | nums[mid] | decision |
|---|---|---|---|
| 0 / 6 | 3 | 7 | 7 < 9 → lo = 4 |
| 4 / 6 | 5 | 11 | 11 > 9 → hi = 4 |
| Key step: 4 / 4 | 4 | 9 | found; return 4 |
Invariant: Before and after every iteration, if the target exists in nums, its index is inside [lo, hi].
Reusable template
The shape to adapt for a new problem in this pattern.
python
Common mistakes
- Using mid = (lo + hi) // 2 in languages where lo + hi can overflow (not a Python issue, but a habit worth naming out loud).
- Off-by-one bounds: lo <= hi vs lo < hi depends on whether hi is inclusive — mixing conventions mid-solution causes infinite loops or missed answers.
- Forgetting mid ± 1 and re-checking the same mid forever.
- Applying binary search to data that isn't actually monotonic on the property you're testing.
- For boundary search (first/last true), returning as soon as a match is found instead of continuing to narrow toward the boundary.
Practice: easy → medium → timed check
Solve in order; each step adds one decision to the same pattern.
1. Binary Search
EasyNot solved yetThe base template
2. Search Insert Position
EasyNot solved yetBoundary search, not exact match
3. Search in Rotated Sorted Array
MediumNot solved yetFind the sorted half first
4. Find Minimum in Rotated Sorted Array
MediumNot solved yetBoundary search on rotation point
5. Search a 2D Matrix
MediumNot solved yetTreat a 2D grid as one sorted line
Final timed check
Run a 30-minute mock covering this pattern; state the invariant before coding, then finish with complexity and edge cases.
Next lesson
Tree Traversal