Two indices moving with purpose turn an O(n²) nested loop into a single O(n) pass. The trick only works when the data is ordered — and that ordering is what tells each pointer which way to move.
Controls
target sum16
Pointers in Motion
step 0
Insight
Two pointers work when moving one of them reliably changes the answer in a known direction. On a sorted array, moving left rightwards can only increase the sum.
comparisons0
brute force0
best so far–
Complexity
Two pointersO(n)
Brute forceO(n²)
SpaceO(1)
Two Pointers
One pass instead of two nested loops — when the data lets you rule things out.
Quick Context
The two pointers technique uses two indices moving through a sequence in a coordinated way. It typically replaces a nested loop, turning O(n²) into O(n) with no extra memory.
The Classic: Pair Sum
Find two numbers in a sorted array that sum to a target. Brute force checks all pairs: O(n²). Two pointers starts one at each end:
Sum too small? Move the left pointer right — only larger values lie that way.
Sum too large? Move the right pointer left — only smaller values lie that way.
Exactly right? Done.
Each move eliminates an entire set of pairs from consideration without ever testing them. The pointers only ever move toward each other, so the whole search is one pass.
Why Sorting Is Essential
The technique depends on knowing what moving a pointer does. On a sorted array, moving left rightwards can only increase the sum — that guarantee is what makes it safe to discard everything you skipped.
On unsorted data no such guarantee exists, and the method is simply wrong. If your input is not sorted you must either sort first (O(n log n)) or use a hash set instead (O(n) time, O(n) space).
The Three Patterns
Converging — start at both ends and move inward. Pair sum, palindromes, container with most water.
Same direction (fast/slow) — both start at the left, one advances faster. Removing duplicates in place, finding the middle of a linked list, cycle detection.
Two sequences — one pointer per array. Merging sorted arrays, which is exactly the merge step in merge sort.
Container With Most Water
A subtler case worth understanding. Given heights, pick two lines forming the largest water container. Area is min(height) × width.
Start wide and always move the shorter line inward. Why is that safe? Moving the taller one can only reduce the width while the area stays capped by the same shorter line — so it can never improve. Moving the shorter one at least gives a chance of a taller limit. That single argument is what makes the greedy pointer movement correct.
Interactive Exploration Guide
Run pair sum and step through. Watch each move discard a whole block of pairs the brute force would have tested.
Compare the two counters. Two pointers does roughly n comparisons where brute force does n²/2.
Change the target so no pair exists. The pointers still meet in one pass and correctly report failure.
Try the palindrome check — the same converging pattern, comparing characters instead of summing.
Run container with most water and watch it always move the shorter bar. That is the greedy choice the correctness argument justifies.
Key Takeaway
Two pointers replaces nested loops with a single coordinated pass, in O(1) extra space. It works only when moving a pointer changes the result predictably — usually because the data is sorted. Recognising that condition is the whole skill.
Cheat sheet
Two Pointers
Two indices moving with purpose turn an O(n²) nested loop into a single O(n) pass. The trick only works when the data is ordered — and that ordering is what tells each pointer which way to move.