One core pattern - multiple approaches. Each variation solves a different set of problems.
Loading problems…
Deep Dive Tutorial
Two pointers is fundamentally a prune-and-search strategy. You maintain two indices and at each step you move at least one of them, eliminating solutions that can't possibly be optimal. The key insight is that the structure of the problem (sorted array, or a monotonic relationship between the pointer positions and the answer) lets you safely discard large chunks of the search space with each move.
Three Pointer Configurations
Configuration
Start Positions
Classic Problems
Opposite ends
i=0, j=n-1, move toward center
Two Sum (sorted), Container With Most Water, Reverse
Same direction
i=0, j=0, j runs ahead
Remove duplicates, partition, slow/fast
Slow + fast (LL)
slow=head, fast=head
Cycle detection, middle of LL, kth from end
triangle-alert
When NOT to use two pointers: if the input contains negative values, adding an element can both increase AND decrease the sum. The window no longer has monotonic behavior — shrinking from the left doesn't guarantee we get closer to the target. Use prefix sum + hashmap instead.
Core Template
Opposite-ends template (two sum on sorted array)
let left = 0, right = arr.length - 1;
while (left < right) {
const val = compute(arr[left], arr[right]);
if (val === target) return [left, right];
else if (val < target) left++; // need bigger → move left forward
else right--; // need smaller → move right back
}
Same-direction template (remove/filter in-place)
let slow = 0;
for (let fast = 0; fast < n; fast++) {
if (shouldKeep(arr[fast])) {
arr[slow] = arr[fast];
slow++;
}
}
return slow; // new length
Two pointer decision guide: - "Find pair with sum = target in sorted array" → left/right converging pointers - "3Sum / 4Sum" → fix k-2 elements with loops, two pointers for final pair - "Partition array by condition" → slow/fast or lo/mid/hi (Dutch flag) - "Container / area maximization" → greedy: move the limiting (smaller) side inward - "Valid palindrome with one deletion" → two pointers + helper check on mismatch - "Linked list intersection" → equalize path lengths by switching lists
While loop condition rule: access curr.next → while (curr). Access curr.next.next → while (curr && curr.next).