---
title: 'Two Pointers'
description: 'Converging/parallel index walk that prunes the O(n^2) pair space using order.'
---
## The idea
Checking every pair costs O(n²). That is n² boxes to open.
But if the array is **ordered**, you do not need every pair.
Put one pointer at each end. Look at the sum:
- Too small? Only a bigger left value can help. Move left in.
- Too big? Only a smaller right value can help. Move right in.
Each move kills a whole row of the pair space. O(n²) → O(n).
## The picture
```mermaid
flowchart TD
A["2 7 11 15 target 18
L R"] --> B["2 + 15 = 17 < 18
too small → move L right"]
B --> C["2 7 11 15
L R"]
C --> D["7 + 15 = 22 > 18
too big → move R left"]
D --> E["2 7 11 15
L R"]
E --> F["7 + 11 = 18 ✓"]
style F fill:#2e7d32,color:#fff
```
## Not the same as binary search
Binary search **jumps** to the middle and discards half unseen — O(log n).
Two pointers **walks** — every element gets inspected once — O(n).
Both need order. Different moves.
## Two Sum II (LC 167) — the pure template
```python
def two_sum(numbers: list[int], target: int) -> list[int]:
lo, hi = 0, len(numbers) - 1
while lo < hi:
total = numbers[lo] + numbers[hi]
if total == target:
return [lo + 1, hi + 1]
if total < target:
lo += 1 # only a bigger value helps
else:
hi -= 1 # only a smaller value helps
```
## Container With Most Water (LC 11) — move the shorter wall
Water = width × shorter wall.
Moving the taller wall can never help — width shrinks, height cannot grow.
So always move the shorter one. Say this proof in the interview.
```python
def max_area(height: list[int]) -> int:
lo, hi = 0, len(height) - 1
best = 0
while lo < hi:
best = max(best, (hi - lo) * min(height[lo], height[hi]))
if height[lo] < height[hi]:
lo += 1
else:
hi -= 1
return best
```
## 3Sum (LC 15) — fix one, converge two
Sort first. Fix the smallest number. Now it is Two Sum II on the rest.
Skip duplicates at every level or you get repeat triplets.
```python
def three_sum(nums: list[int]) -> list[list[int]]:
nums.sort()
result = []
for i in range(len(nums) - 2):
if i > 0 and nums[i] == nums[i - 1]:
continue # skip duplicate anchor
lo, hi = i + 1, len(nums) - 1
while lo < hi:
total = nums[i] + nums[lo] + nums[hi]
if total < 0:
lo += 1
elif total > 0:
hi -= 1
else:
result.append([nums[i], nums[lo], nums[hi]])
lo += 1
while lo < hi and nums[lo] == nums[lo - 1]:
lo += 1 # skip duplicate pair
return result
```
## Complexity
| | Time | Space |
|---|---|---|
| Converging pair | O(n) | O(1) |
| 3Sum | O(n²) — sort + n passes | O(1) extra |
## Close-out ritual
Before you submit, say out loud:
1. Time and space complexity.
2. One edge case trace: two elements, all duplicates, or no valid answer.
## Plan problems
**A-set:** LC 125 · 167 · 15 · 11 · 42
**B-set:** LC 392 · 977 · 189 · 80