Here's the question: in this sorted array, which two numbers add up to 10?
- Index 0: 1
- Index 1: 3
- Index 2: 4
- Index 3: 6
- Index 4: 8
- Index 5: 11
Brute force tries every pair: 15 of them here, n² / 2 in general. Two pointers finds the answer in 5 steps, and the reason is worth seeing rather than memorising.
One comparison rules out a whole row
Put one pointer on the smallest number and one on the largest, and add them.
- Index 0: 1 (L)
- Index 1: 3
- Index 2: 4
- Index 3: 6
- Index 4: 8
- Index 5: 11 (R: out)
12 is over the target. That doesn't just rule out the pair (1, 11): 1 is the smallest number in the array, so 11 plus anything else is even bigger. Every pair containing 11 is now dead, and one comparison removed five pairs.
- Index 0: 1 (L: out)
- Index 1: 3
- Index 2: 4
- Index 3: 6
- Index 4: 8 (R)
- Index 5: 11
The mirror image: 9 is under the target, and 8 is the largest number still in play, so 1 can't reach 10 with anything. Drop 1.
That's the whole pattern. Too big, move the right pointer in; too small, move the left pointer in. Each step permanently deletes one number, so the walk ends in at most n steps.
| Step | L | R | Sum | Decision |
|---|---|---|---|---|
| 1 | 1 | 11 | 12 | too big, drop 11 |
| 2 | 1 | 8 | 9 | too small, drop 1 |
| 3 | 3 | 8 | 11 | too big, drop 8 |
| 4 | 3 | 6 | 9 | too small, drop 3 |
| 5 | 4 | 6 | 10 | found |
The sort is what makes the "drop" safe. On unsorted input, 1 isn't guaranteed to be the smallest partner, the reasoning breaks, and the pointers silently skip valid answers.
Two indices, one loop
time and space. If you have to sort the input first,
the sort dominates. The guard is left < right because
a pair needs two distinct elements; use <= only when a single middle
element is a valid answer.
Same move, other shapes
The pointers don't always start at opposite ends. What stays the same is that a single comparison tells you which side can never help.
| Shape | Pointers | Classic problems |
|---|---|---|
| Opposite ends | close in from both sides | pair sums, palindromes, container |
| Read and write | both from the left, one lags | in-place dedupe, move zeroes to the end |
| Fast and slow | one moves twice as fast | cycle detection, middle of a linked list |
| Sliding window | both from the left, keep a total | longest substring, subarray sums |
When a problem says "sorted", "in place", "O(1) extra space" or "find two that...", ask which side one comparison lets you throw away. If you can answer, it's two pointers.