mirror of
https://github.com/prdlk/leetcode.git
synced 2026-11-02 21:22:43 +00:00
docs(docs): add two‑pointer guide with decision tree and illustrations
This commit is contained in:
1 parent
030887c7df
commit
f202c3a0a1
8 files changed
+656
No files matched your search
@@ -3,3 +3,160 @@ title: Two Pointers
|
||||
description: 'Two indices move through the data from different positions and meet at the answer.'
|
||||
hidden: true
|
||||
---
|
||||
|
||||
Most interview problems in this section fall into one of four families:
|
||||
|
||||
- **Same direction pointers**: one pointer reads, one pointer writes, or one pointer stays behind another while scanning left to right.
|
||||
- **Opposite direction pointers**: one pointer starts on the left, one on the right, and each move eliminates impossible answers.
|
||||
- **Sliding window**: the two pointers define a contiguous interval, and you maintain some property of that interval as the window expands and shrinks.
|
||||
- **Fast and slow pointers**: both pointers move through a linked structure, but at different speeds or with a fixed gap.
|
||||
|
||||

|
||||
|
||||
## Same Direction
|
||||
|
||||
Same-direction pointer problems usually scan from left to right, but the two pointers do different jobs.
|
||||
|
||||
Usually:
|
||||
|
||||
- one pointer reads the next value from the original input
|
||||
- one pointer marks where the next kept value should go
|
||||
|
||||
Sometimes both pointers move forward together, but one pointer stays behind the other to preserve a gap or a relationship.
|
||||
|
||||
### When this family applies
|
||||
|
||||
|
||||
Reach for same-direction pointers when the problem asks you to:
|
||||
|
||||
- rewrite an array in-place
|
||||
- remove or compress elements without extra memory
|
||||
- keep only the values that satisfy some condition
|
||||
- maintain a fixed gap between two forward-moving pointers
|
||||
|
||||
### Core Invariant
|
||||
|
||||
The invariant in this family is usually about the prefix you have already processed.
|
||||
|
||||
Typical invariant:
|
||||
|
||||
> "Everything before the write pointer is already in the correct final form."
|
||||
|
||||
That is what makes these problems feel different from opposite-direction scans. You are not searching from both sides. You are building the answer progressively as you sweep through the input.
|
||||
|
||||
### Subtypes in this section
|
||||
|
||||
#### 1. Compaction / Overwrite
|
||||
|
||||
The slow pointer marks the next output position. The fast pointer scans the input. When the current value should be kept, copy it forward and advance the slow pointer.
|
||||
|
||||

|
||||
|
||||
#### 2. Relative Speed
|
||||
|
||||
Both pointers move forward, but one moves twice as fast. The invariant is about their distance and how much of the structure each pointer has consumed.
|
||||
|
||||

|
||||
|
||||
#### 3. Fixed Gap
|
||||
|
||||
Both pointers move forward while preserving a gap. The invariant is not about a rewritten prefix. It is about the distance between the pointers.
|
||||
|
||||

|
||||
|
||||
### What changes across problems
|
||||
|
||||
The family stays the same, but the invariant changes slightly:
|
||||
|
||||
- in array compaction, the invariant is about the prefix being correct
|
||||
- in fast/slow midpoint problems, the invariant is about relative speed
|
||||
- in fixed-gap problems, the invariant is about distance
|
||||
|
||||
So the unifying idea is not "both pointers move right." The unifying idea is:
|
||||
|
||||
**"the structure to the left of the pointers already has a known meaning"**
|
||||
|
||||
### What to watch out for
|
||||
|
||||
Common mistakes:
|
||||
|
||||
- Updating the write pointer before copying the current value.
|
||||
- Forgetting exactly what region is already valid.
|
||||
- Losing track of whether the invariant is about a prefix, a gap, or relative speed.
|
||||
|
||||
As you go through the following problems, pay attention to one question:
|
||||
|
||||
**What does the region before the slow pointer mean right now?**
|
||||
|
||||
## Opposite Direction
|
||||
|
||||
Opposite-direction pointer problems place one pointer on the left and one on the right, then move inward.
|
||||
|
||||
The hard part is never the loop itself. **The hard part is justifying which pointer is safe to move.**
|
||||
|
||||
### When this family applies
|
||||
|
||||
Reach for opposite-direction pointers when the problem asks you to:
|
||||
|
||||
- the input is sorted, or can be made monotonic by sorting
|
||||
- you are comparing a left choice and a right choice
|
||||
- the problem has symmetry
|
||||
- moving one side lets you eliminate a set of impossible answers
|
||||
|
||||
### Core Invariant
|
||||
|
||||
The invariant in this family is usually:
|
||||
|
||||
> "All candidate answers outside the current `[left, right]` range have already been ruled out."
|
||||
|
||||
That means each move must come with a proof. If you move a pointer without knowing why the discarded cases cannot contain the optimum, the algorithm is just guessing.
|
||||
|
||||
### Subtypes in this section
|
||||
|
||||
#### 1. Monotonic sum elimination
|
||||
|
||||
|
||||
Because the array is sorted:
|
||||
|
||||
- if the sum is too small, moving the left pointer right is the only useful move
|
||||
- if the sum is too large, moving the right pointer left is the only useful move
|
||||
|
||||
Sorted order gives you a monotonic rule.
|
||||
|
||||

|
||||
|
||||
#### 2. Symmetry checking
|
||||
|
||||
Here the pointers compare mirrored positions. The movement rule is mostly "move both," except when you must skip punctuation or spaces.
|
||||
|
||||

|
||||
|
||||
#### 3. Bottleneck elimination
|
||||
|
||||
This one is important because it looks different from the other two. The key idea is that the shorter wall limits the area. If you keep that shorter wall and decrease the width, you cannot improve the answer. So it is safe to discard that wall.
|
||||
|
||||

|
||||
|
||||
### Why this is not a sliding window
|
||||
|
||||
Opposite-direction scans do not maintain an interval property like "this window is valid."
|
||||
|
||||
Instead, each step does one of these:
|
||||
|
||||
- rules out sums that are too small or too large
|
||||
- checks mirrored characters
|
||||
- discards a bottleneck boundary
|
||||
|
||||
The interval itself is just the remaining search space.
|
||||
|
||||
### What to watch out for
|
||||
|
||||
Common mistakes:
|
||||
|
||||
- Using two pointers on an unsorted pair problem without first creating monotonicity.
|
||||
- Moving the taller wall in Container With Most Water without an elimination proof.
|
||||
- Calling the method sliding window just because two boundaries exist.
|
||||
|
||||
As you read the problems in this family, keep asking:
|
||||
|
||||
**What exact set of candidate answers did this pointer move eliminate?**
|
||||
Reference in new issue
Block a user