Two Pointers
Two pointers is a pattern in which you maintain two pointers (left, right) and move them based on the problem’s condition. In programming problem solving, a “pointer” usually refers to an index or position (reference) into the data—especially in strings and array problems.
Common patterns
Section titled “Common patterns”Opposite sides
Section titled “Opposite sides”One pointer starts at the beginning, the other at the end; they move toward each other. Best for sorted arrays where you need to find pairs or compare elements from both ends.
Initial: [2, 7, 11, 15] ↑ ↑ left right
After: [2, 7, 11, 15] ↑ ↑ left rightUse when: Two Sum, Valid Palindrome, Container With Most Water
Same direction
Section titled “Same direction”Both pointers start at one end and move in the same direction. The “fast” pointer scans ahead while the “slow” pointer writes valid elements. Best for in-place filtering or transformation.
Initial: [1, 1, 2, 3, 3] ↑ ↑ slow fast
After: [1, 2, 3, 3, 3] ↑ ↑ slow fastUse when: Remove Duplicates, Move Zeros, Remove Element
Example: Opposite sides — Two Sum II
Section titled “Example: Opposite sides — Two Sum II”Given a sorted array and a target, find two numbers that add up to the target. Start with left at index 0 and right at the last index. If the sum is less than the target, move left right; if greater, move right left. Returns 0-indexed indices.
Array: [2, 7, 11, 15], Target: 9 ↑ ↑ left right (2+15=17 > 9, right--)
↑ ↑ left right (2+11=13 > 9, right--)
↑ ↑ left right (2+7=9 == 9, found!)def two_sum(nums: list[int], target: int) -> list[int]: left, right = 0, len(nums) - 1 while left < right: total = nums[left] + nums[right] if total < target: left += 1 elif total > target: right -= 1 else: return [left, right] return []vector<int> twoSum(vector<int>& nums, int target) { int left = 0, right = nums.size() - 1; while (left < right) { int sum = nums[left] + nums[right]; if (sum < target) left++; else if (sum > target) right--; else return {left, right}; } return {};}public int[] twoSum(int[] nums, int target) { int left = 0, right = nums.length - 1; while (left < right) { int sum = nums[left] + nums[right]; if (sum < target) left++; else if (sum > target) right--; else return new int[]{left, right}; } return new int[0];}Example: Same direction — Remove Duplicates from Sorted Array
Section titled “Example: Same direction — Remove Duplicates from Sorted Array”Remove duplicates in-place and return the new length. slow is the write index, fast is the read index. When nums[fast] != nums[slow], increment slow and copy nums[fast] to nums[slow]. Return slow + 1.
Array: [1, 1, 2, 3, 3] ↑ ↑ slow fast (1==1, fast++)
↑ ↑ slow fast (1!=2, slow++, copy)
↑ ↑ slow fast (2!=3, slow++, copy)
↑ ↑ slow fast (3==3, fast++)
Return: slow + 1 = 3Result: [1, 2, 3, ...]def remove_duplicates(nums: list[int]) -> int: if not nums: return 0 slow = 0 for fast in range(1, len(nums)): if nums[fast] != nums[slow]: slow += 1 nums[slow] = nums[fast] return slow + 1int removeDuplicates(vector<int>& nums) { if (nums.empty()) return 0; int slow = 0; for (int fast = 1; fast < nums.size(); fast++) { if (nums[fast] != nums[slow]) { slow++; nums[slow] = nums[fast]; } } return slow + 1;}public int removeDuplicates(int[] nums) { if (nums == null || nums.length == 0) return 0; int slow = 0; for (int fast = 1; fast < nums.length; fast++) { if (nums[fast] != nums[slow]) { slow++; nums[slow] = nums[fast]; } } return slow + 1;}Quick reference
Section titled “Quick reference”Pattern identification
Section titled “Pattern identification”| Pattern | Description | Example Problem | Category |
|---|---|---|---|
| Sorted Array | If the input array is sorted and you are asked about pairs or triplets or subarrays | Two Sum in Sorted Array, 3Sum | Opposite sides |
| Palindrome or matching | Check if a string or array is a palindrome | Valid Palindrome | Opposite sides |
| Remove or skip elements | Problems like remove duplicates, move zeros, rearrange | Remove Duplicates from Sorted Array | Same direction |
| Min/Max length of subarray | If asked about subarray sums, min/max length | Minimum Size Subarray Sum | Same direction |
| Find window | Problems about sliding a window over the array | Longest substring without repeating characters | Same direction |
Implementation reference
Section titled “Implementation reference”| Pattern | Initial | Movement | Complexity |
|---|---|---|---|
| Opposite sides | left=0, right=n-1 | left++ or right-- based on condition | O(n) |
| Same direction | slow=0, fast=0/1 | fast always advances; slow moves conditionally | O(n) |