--- title: 'Two Pointers' description: 'Converging/parallel index walk that prunes the O(n^2) pair space using order.' --- ## The idea Checking every pair costs O(n²). That is n² boxes to open. But if the array is **ordered**, you do not need every pair. Put one pointer at each end. Look at the sum: - Too small? Only a bigger left value can help. Move left in. - Too big? Only a smaller right value can help. Move right in. Each move kills a whole row of the pair space. O(n²) → O(n). ## The picture ```mermaid flowchart TD A["2 7 11 15 target 18
L R"] --> B["2 + 15 = 17 < 18
too small → move L right"] B --> C["2 7 11 15
L R"] C --> D["7 + 15 = 22 > 18
too big → move R left"] D --> E["2 7 11 15
L R"] E --> F["7 + 11 = 18 ✓"] style F fill:#2e7d32,color:#fff ``` ## Not the same as binary search Binary search **jumps** to the middle and discards half unseen — O(log n). Two pointers **walks** — every element gets inspected once — O(n). Both need order. Different moves. ## Two Sum II (LC 167) — the pure template ```python def two_sum(numbers: list[int], target: int) -> list[int]: lo, hi = 0, len(numbers) - 1 while lo < hi: total = numbers[lo] + numbers[hi] if total == target: return [lo + 1, hi + 1] if total < target: lo += 1 # only a bigger value helps else: hi -= 1 # only a smaller value helps ``` ## Container With Most Water (LC 11) — move the shorter wall Water = width × shorter wall. Moving the taller wall can never help — width shrinks, height cannot grow. So always move the shorter one. Say this proof in the interview. ```python def max_area(height: list[int]) -> int: lo, hi = 0, len(height) - 1 best = 0 while lo < hi: best = max(best, (hi - lo) * min(height[lo], height[hi])) if height[lo] < height[hi]: lo += 1 else: hi -= 1 return best ``` ## 3Sum (LC 15) — fix one, converge two Sort first. Fix the smallest number. Now it is Two Sum II on the rest. Skip duplicates at every level or you get repeat triplets. ```python def three_sum(nums: list[int]) -> list[list[int]]: nums.sort() result = [] for i in range(len(nums) - 2): if i > 0 and nums[i] == nums[i - 1]: continue # skip duplicate anchor lo, hi = i + 1, len(nums) - 1 while lo < hi: total = nums[i] + nums[lo] + nums[hi] if total < 0: lo += 1 elif total > 0: hi -= 1 else: result.append([nums[i], nums[lo], nums[hi]]) lo += 1 while lo < hi and nums[lo] == nums[lo - 1]: lo += 1 # skip duplicate pair return result ``` ## Complexity | | Time | Space | |---|---|---| | Converging pair | O(n) | O(1) | | 3Sum | O(n²) — sort + n passes | O(1) extra | ## Close-out ritual Before you submit, say out loud: 1. Time and space complexity. 2. One edge case trace: two elements, all duplicates, or no valid answer. ## Plan problems **A-set:** LC 125 · 167 · 15 · 11 · 42 **B-set:** LC 392 · 977 · 189 · 80