patternDSA/Two Pointers
Core Pattern → Pattern 06

Two Pointers

Replace nested loops with coordinated pointers. One pointer narrows from each end, or two move in lockstep — both eliminate redundant comparisons entirely.

Frequency:★★★★★
·~40 min·Intermediate·13 problems
The Core Shock

Find a pair summing to target — n² comparisons vs n steps

Brute Force (Unsorted)
n² comparisons
n=10,000: up to 50,000,000 checks
O(n²)
Two Pointers (Sorted)
≤ n steps
n=10,000: at most 10,000 steps
O(n)

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.

Opposite Ends

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.

Test: Ask: 'Is the array sorted, and am I searching for a pair?' If yes → opposite ends.
Pair With Target SumContainer With Most WaterTwo Sum IITriplet Sum to ZeroReverse String
Same Direction

Both L and R start at index 0. R (fast) explores ahead. L (slow) marks a boundary or write position. No sort required.

Test: Ask: 'Am I removing/overwriting in-place, or does one pointer lag behind?' If yes → same direction.
Remove DuplicatesMove ZerosFind Non-Duplicate InstancesComparing Strings with BackspacesMinimum Window Sort

The 3-Step Two Pointer Framework

The three decisions you make before writing a single loop.

01
Sort (if needed) + Initialize Pointers

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
Sorting is O(n log n) — still better than O(n²) brute force. If the array is already sorted, two pointers are pure O(n).
02
Define Move Condition

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 -= 1
The move condition is the heart of the pattern. State it precisely before coding. Wrong condition = infinite loop or missed answers.
03
Handle Duplicates

In 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 duplicates
Duplicate handling is the most common source of wrong answers in multi-sum problems. Test with input like [-1,-1,0,1,1,2] before submitting.

Pattern Recognition

30-second diagnosis: is this two pointers?

Use Two Pointers When
"Find pair/triplet summing to target"
Sorted array or you can sort first
Need O(1) space (no HashMap allowed)
"Remove duplicates / move elements in-place"
"Squaring sorted array"
"Container / trap most water"
"Reverse array in-place"
Compare two strings with virtual deletions
Do NOT Use Two Pointers When
Unsorted + cannot sort (order matters)
Need indices of original positions after sort
Contiguous subarray → use Sliding Window
Cycle detection → use Fast & Slow Pointers
Array is not linear (graph, tree, matrix)
Need O(1) lookup for arbitrary values → HashMap