mirror of
https://github.com/prdlk/leetcode.git
synced 2026-11-02 21:22:43 +00:00
117 lines
3.2 KiB
Plaintext
117 lines
3.2 KiB
Plaintext
---
|
||
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<br/>L R"] --> B["2 + 15 = 17 < 18<br/>too small → move L right"]
|
||
B --> C["2 7 11 15<br/> L R"]
|
||
C --> D["7 + 15 = 22 > 18<br/>too big → move R left"]
|
||
D --> E["2 7 11 15<br/> 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
|