2026-08-19 11:20:34 -04:00
---
title: 'Binary Search'
description: 'In algorithms, arrays and strings are very similar. They are both ordered collections of elements. The difference is that arrays are mutable, while strings are immutable.'
---
2026-08-20 16:04:24 -04:00
## The idea
2026-08-19 11:20:34 -04:00
2026-08-20 16:04:24 -04:00
You look for a name in a phone book. You do not start at page 1.
You open the middle. Too far? Go left. Not far enough? Go right.
Each step throws away half the book.
2026-08-19 11:20:34 -04:00
2026-08-20 16:04:24 -04:00
100 items → 7 steps. 4 billion items → 32 steps.
2026-08-19 11:20:34 -04:00
2026-08-20 16:04:24 -04:00
**The core rule:** ask a yes/no question that flips exactly once.
Everything left of the flip is "no". Everything right is "yes".
Binary search finds the flip point.
2026-08-19 11:20:34 -04:00
2026-08-20 16:04:24 -04:00
## The picture
2026-08-19 11:20:34 -04:00
2026-08-20 16:04:24 -04:00
```mermaid
flowchart TD
A["Array: 1 3 5 7 9 11 13<br/>Target: 9"] --> B["mid = 7<br/>7 < 9 → discard left half"]
B --> C["Array: 9 11 13<br/>mid = 11<br/>11 > 9 → discard right half"]
C --> D["Array: 9<br/>mid = 9<br/>Found ✓"]
2026-08-19 11:20:34 -04:00
2026-08-20 16:04:24 -04:00
style D fill:#2e7d32,color:#fff
```
2026-08-19 11:20:34 -04:00
2026-08-20 16:04:24 -04:00
## The template
2026-08-19 13:05:47 -04:00
2026-08-20 16:04:24 -04:00
```python
def binary_search(nums: list[int], target: int) -> int:
lo, hi = 0, len(nums) - 1
2026-08-19 13:05:47 -04:00
2026-08-20 16:04:24 -04:00
while lo <= hi:
mid = (lo + hi) // 2
if nums[mid] == target:
return mid
if nums[mid] < target:
lo = mid + 1
else:
hi = mid - 1
return -1
```
## Search the answer space (LC 875 — Koko Eating Bananas)
The array does not need to exist. You can binary search over *possible answers*.
Ask: "does speed k work?" Slow speeds fail. Fast speeds work.
The answer flips once. Find the flip.
```mermaid
flowchart LR
A["k=1<br/>NO"] --> B["k=2<br/>NO"] --> C["k=3<br/>NO"] --> D["k=4<br/>YES ← answer"] --> E["k=5<br/>YES"] --> F["k=6<br/>YES"]
style D fill:#2e7d32,color:#fff
```
```python
import math
def min_eating_speed(piles: list[int], h: int) -> int:
def k_works(k: int) -> bool:
return sum(math.ceil(p / k) for p in piles) <= h
lo, hi = 1, max(piles)
while lo < hi:
mid = (lo + hi) // 2
if k_works(mid):
hi = mid # mid works — keep it, look left
else:
lo = mid + 1 # mid fails — discard it
return lo
```
## Not the same as two pointers
Two pointers **walks** — it inspects every element it passes. O(n).
Binary search **jumps** — it inspects one midpoint and discards half unseen. O(log n).
## Complexity
| | Time | Space |
|---|---|---|
| Sorted array | O(log n) | O(1) |
| Answer space | O(n log m) | O(1) |
n = array size, m = answer range.
## Close-out ritual
Before you submit, say out loud:
1. Time and space complexity.
2. One edge case trace: empty array, one element, or target not present.
## Plan problems
**A-set:** LC 704 · 74 · 875 · 33 · 153
**B-set:** LC 35 · 162 · 34 · 4 ⭐