Core Idea: Maintain two positions in data structure and move them based on conditions. Avoids nested loops (O(n²) → O(n)).
Convergent: Start at both ends (i=0, j=n-1), move inward based on condition.
Same Direction: Both move left-to-right at different speeds (sliding window).
Why It Works: Each pointer moves at most n times = O(n) total. Compare this to brute force checking all pairs = O(n²).
Goal: Check if string is palindrome (ignoring non-alphanumeric, case-insensitive).
Why Two Pointers? Palindrome = symmetric. Compare first with last, second with second-last, etc. Two pointers naturally express this symmetry. Alternative (reverse string) uses O(n) space; this uses O(1).
Key Insight: Skip invalid characters while maintaining pointer positions. Inner loops advance past non-alphanumeric before comparing. Only move to next comparison when both pointers point to valid chars.
Trap:
Check `i < j` in skip loops to avoid index errors.Goal: Find two numbers in sorted array that sum to target.
Why Two Pointers? Array is sorted—this is the key! If sum too small, need bigger number (move left pointer right). If sum too large, need smaller number (move right pointer left). Hash map works but uses O(n) space; problem demands O(1).
Key Insight: Sorted array gives direction. Each comparison eliminates one possibility. Pointers always converge because we're monotonically narrowing search space. Can't miss the answer.
Sorted Required:
Won't work on unsorted array. Sort first if needed.Goal: Find all unique triplets that sum to zero.
Why This Approach? Brute force is O(n³) checking all triplets. Instead, fix first element, then use two pointers for remaining two (O(n) for each fixed element = O(n²) total). Must sort first to enable two pointer technique and skip duplicates efficiently.
Key Insight: After sorting, fix `i`, search for `j,k` where `nums[i]+nums[j]+nums[k]=0`. This reduces 3Sum to many 2Sum problems. Dedup by skipping consecutive equal values at all three positions.
Dedup Critical:
Must skip duplicates at all 3 positions to avoid duplicate triplets.Goal: Find two bars that form container with max water area.
Why Greedy Works? Area = min(h[i], h[j]) × (j - i). Start with max width (i=0, j=n-1). To improve area, we need taller bars. Moving the taller pointer only decreases width without potential height gain. Moving shorter pointer might find taller bar. This greedy choice is optimal.
Key Insight: We never miss optimal solution. When we move shorter pointer, we're abandoning all pairs with current pointer (proven to be suboptimal due to width decrease). Each step eliminates possibilities that can't be better.
Proof Sketch: If h[i]
Goal: Calculate water trapped between elevation bars.
Why This Works? Water at position i = min(leftMax, rightMax) - h[i]. Brute force: for each position, scan left and right for max (O(n²)). Precompute arrays: O(n) time but O(n) space. Two pointers: track maxes while moving, O(1) space!
Key Insight: Water level determined by shorter wall. If leftMax < rightMax, we KNOW water at left pointer is limited by leftMax (rightMax is guaranteed higher). Process left side. Vice versa for right. Only need to track which side is limiting factor.
Subtle Point: We don't need exact max on both sides, just need to know which side is limiting. The smaller of leftMax/rightMax determines water level.
Use When: Sorted array, palindrome check, optimization with width×height.
Examples: Two Sum II, Valid Palindrome, Container With Most Water.
Template: `l=0, r=n-1; while l Use When: Finding k-tuples (triplets, quadruplets) that satisfy condition. Examples: 3Sum, 4Sum. Template: `for i: {l=i+1, r=n-1; two pointer search}` Use When: Optimization problem where one pointer choice is clearly better. Examples: Container With Most Water (move shorter bar). Key: Prove moving one pointer can't miss optimal solution. Use When: Need to maintain running state (max, min, sum) while traversing. Examples: Trapping Rain Water (track leftMax/rightMax). Key: Update state variables as pointers move. Common Thread:2. Fixed + Two Pointers:
3. Greedy Pointer Movement:
4. State Tracking Pointers: