Two Pointers
Replace nested loops with coordinated pointers. One pointer narrows from each end, or two move in lockstep — both eliminate redundant comparisons entirely.
Find a pair summing to target — n² comparisons vs n steps
The insight: a sorted array encodes direction. If the two-pointer sum is too small, the only way to increase it is to move the left pointer right. If too large, move the right pointer left. Each step eliminates one element permanently — at most n steps total.
The Two Pointer Types
Every two-pointer problem uses one of these. Identify which before coding.
L starts at index 0, R starts at the last index. They move toward each other. Requires sorted input — sort order tells you which pointer to move.
Both L and R start at index 0. R (fast) explores ahead. L (slow) marks a boundary or write position. No sort required.
The 3-Step Two Pointer Framework
The three decisions you make before writing a single loop.
Opposite ends: sort first, set L=0, R=n-1. Same direction: no sort needed, set slow=0, fast=0 or fast=1. The sort decision is the whole strategy.
arr.sort() # opposite ends needs sorted left, right = 0, len(arr) - 1
Opposite ends: compare sum to target. sum < target → L right. sum > target → R left. Same direction: R always advances; slow advances only on a valid condition.
if current_sum < target:
left += 1
elif current_sum > target:
right -= 1In Three Sum and similar: after finding a valid answer, skip all duplicate values for both L and R. Otherwise the result set contains duplicate triplets.
while left < right and arr[left] == arr[left+1]:
left += 1 # skip left duplicates
while left < right and arr[right] == arr[right-1]:
right -= 1 # skip right duplicatesPattern Recognition
30-second diagnosis: is this two pointers?