Two Pointers
Walk pointers toward each other to cut a quadratic search down to one pass.
The idea
Two Pointers is usually the first moment DSA stops feeling like memorization and starts feeling like a trick you own. The idea: instead of checking every pair of elements with two nested loops, you keep two indices and move them with intent โ because the structure of the data (usually sortedness) tells you which moves can be safely skipped.
That's the entire pattern. Everything else โ fast/slow pointers, converging pointers, partition pointers โ is a variation on "my next move is provably safe to make, so I never have to look back."
How to recognize it
- The input is sorted, or you're allowed to sort it without breaking the problem.
- You're looking for a pair, triplet, or range that satisfies a condition (sum, difference, containment).
- The brute force is O(nยฒ) over pairs, and the check for each pair is O(1).
- The phrase "in-place" appears โ partitioning and de-duplication love two pointers.
- It's a linked list and someone said the word "cycle" or "middle" โ that's the fast/slow variant.
When to reach for it
- Pair-with-target-sum in a sorted array (the canonical case).
- Comparing from both ends inward: palindromes, container problems, trapping water.
- Deduplicating or partitioning in place with a read pointer and a write pointer.
- Merging two sorted sequences without extra passes.
The mental model
Think of the sorted array as a grid of all possible pairs (i, j). Brute force visits all of it. Two pointers starts at one corner โ smallest i, largest j โ and every comparison eliminates an entire row or column: if the sum is too small, no pair with this i can work (j is already as big as it gets), so i++ discards the row. Too big? j-- discards the column. Each step kills n possibilities, so n steps finish the job.
The pattern generalizes whenever you can prove that same one-directional claim: "given what I just observed, moving this pointer can only help, and it never needs to move back." If you can't make that argument, two pointers is the wrong tool โ that's not a failure of technique, it's the pattern telling you the structure isn't there.
O(n) time for the standard converging scan (each pointer moves at most n steps total), O(1) extra space. Add O(n log n) if you had to sort first.
Where people get burned
- Using it on unsorted data where the "safe to move" argument doesn't hold โ the answers will be wrong, not slow.
- Off-by-one at the crossing: decide up front whether left < right or left <= right is your loop condition and what it means for your problem.
- In 3Sum-style problems, forgetting to skip duplicate values after a hit โ you'll emit the same triplet repeatedly.
- Moving both pointers on a match without thinking โ sometimes only one side may advance safely.
Practice progression
In this order, on LeetCode. Each one adds a wrinkle the previous one didn't have.
Knowing the pattern is half the job. Showing up daily is the other half.
DSAMotivator tracks this exact progression โ with streaks, XP, and a map that fills in as you go.
Start free โ 7 days