Two Pointers : Patterns & Use Cases
- โ Why to Use this technique?
- ๐ก Pattern 1: Opposite Ends (Converging Pointers)
- ๐ก Pattern 2: Same Direction (Fast & Slow Pointers)
- ๐ก Pattern 3: Linked List Tricks (Cycle, Intersection, Middle)
- ๐ก Pattern 4: One Fixed, One Searching
- ๐ก Pattern 5: Bidirectional Scan
- ๐ก Pattern 6: Merge-Like (Sorted Arrays)
- ๐ก Pattern 7: Partition-Based Scanning
Two Pointer technique uses two indices that traverse the data structure (typically arrays or linked lists) in a coordinated way. Depending on the problem, the pointers can behave as follows:
- Start from both ends and move toward the center
- Move in the same direction
- Move at different speeds
- Reset based on certain conditions
โ Why to Use this technique?
- This technique reduces brute-force approaches
- It Works great with sorted arrays or lists
- It Saves space and improves runtime
๐ก Pattern 1: Opposite Ends (Converging Pointers)
๐ Problem: Leetcode 167 - Two Sum II (Input Array is Sorted)
Given a sorted array of integers, find two numbers such that they add up to a specific target.
๐ง Intuition:
We Start with one pointer at the beginning and one at the end. Since the array is sorted:
- If the sum is too small, we move the left pointer right
- If the sum is too large, we move the right pointer left
โ Code:
public int[] twoSum(int[] numbers, int target) {
int left = 0, right = numbers.length - 1;
while (left < right) {
int sum = numbers[left] + numbers[right];
if (sum == target) return new int[]{left + 1, right + 1};
else if (sum < target) left++;
else right--;
}
return new int[]{-1, -1};
}
โฑ๏ธ Time: O(n) ย ย ๐ Space: O(1)
๐ก Pattern 2: Same Direction (Fast & Slow Pointers)
๐ Problem: Leetcode 26 - Remove Duplicates from Sorted Array
Given a sorted array, remove duplicates in-place.
๐ง Intuition:
Use two pointers:
slow
marks the position to overwritefast
explores the array
โ Code:
public int removeDuplicates(int[] nums) {
int slow = 0;
for (int fast = 1; fast < nums.length; fast++) {
if (nums[fast] != nums[slow]) {
nums[++slow] = nums[fast];
}
}
return slow + 1;
}
โฑ๏ธ Time: O(n) ย ย ๐ Space: O(1)
๐ก Pattern 3: Linked List Tricks (Cycle, Intersection, Middle)
๐ Problem: Leetcode 160 - Intersection of Two Linked Lists
Find the node at which two singly linked lists intersect.
๐ง Intuition:
We use two pointers that switch heads once they reach the end. They will meet at the intersection or both hit null
.
This approach works because by switching the heads when a pointer reaches the end of its list, we ensure that both pointers traverse the same total number of nodes โ one travels A then B, the other B then A. If the two lists intersect, the pointers will align at the intersection after walking the same combined distance. If they donโt intersect, both will reach
null
at the same time. This guarantees either a meeting point (intersection) or a synchronized end, without needing to know the lengths of the lists in advance.
โ Code:
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode a = headA, b = headB;
while (a != b) {
a = (a == null) ? headB : a.next;
b = (b == null) ? headA : b.next;
}
return a;
}
โฑ๏ธ Time: O(m + n) ย ย ๐ Space: O(1)
๐ก Pattern 4: One Fixed, One Searching
๐ Problem: Leetcode 15 - 3Sum
Find all unique triplets in the array which gives the sum of zero.
๐ง Intuition:
- Firstly, letโs Sort the array
- Then we fix the first number and use two pointers to find the remaining two
โ Code:
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> res = new ArrayList<>();
for (int i = 0; i < nums.length - 2; i++) {
if (i > 0 && nums[i] == nums[i - 1]) continue;
int left = i + 1, right = nums.length - 1;
while (left < right) {
int sum = nums[i] + nums[left] + nums[right];
if (sum == 0) {
res.add(Arrays.asList(nums[i], nums[left], nums[right]));
left++; right--;
while (left < right && nums[left] == nums[left - 1]) left++;
while (left < right && nums[right] == nums[right + 1]) right--;
} else if (sum < 0) left++;
else right--;
}
}
return res;
}
โฑ๏ธ Time: O(n^2) ย ย ๐ Space: O(1) (excluding output)
๐ก Pattern 5: Bidirectional Scan
๐ Problem: Leetcode 42 - Trapping Rain Water
Compute how much water can be trapped after raining given elevation map.
๐ง Intuition:
We keep two pointers and track the max height seen so far from both ends.
This approach works because the amount of water that can be trapped at any index depends on the minimum of the maximum heights to its left and right. By using two pointersโone starting from the left and one from the rightโwe can efficiently track the maximum height seen so far from each side (
maxLeft
andmaxRight
). At each step, we move the pointer on the side with the smaller height, because the trapped water at that point is limited by that smaller boundary. This ensures that we only need a single pass through the array, without needing to precompute separate left/right max arrays, achieving O(n) time and O(1) space.
โ Code:
public int trap(int[] height) {
int left = 0, right = height.length - 1;
int maxLeft = 0, maxRight = 0, res = 0;
while (left < right) {
if (height[left] < height[right]) {
if (height[left] >= maxLeft) maxLeft = height[left];
else res += maxLeft - height[left];
left++;
} else {
if (height[right] >= maxRight) maxRight = height[right];
else res += maxRight - height[right];
right--;
}
}
return res;
}
โฑ๏ธ Time: O(n) ย ย ๐ Space: O(1)
๐ก Pattern 6: Merge-Like (Sorted Arrays)
๐ Problem: Leetcode 88 - Merge Sorted Array
Merge two sorted arrays into one in-place.
๐ง Intuition:
We start from the back and fill in the largest values to avoid overwriting.
โ Code:
public void merge(int[] nums1, int m, int[] nums2, int n) {
int i = m - 1, j = n - 1, k = m + n - 1;
while (i >= 0 && j >= 0) {
if (nums1[i] > nums2[j]) nums1[k--] = nums1[i--];
else nums1[k--] = nums2[j--];
}
while (j >= 0) nums1[k--] = nums2[j--];
}
โฑ๏ธ Time: O(m + n) ย ย ๐ Space: O(1)
๐ก Pattern 7: Partition-Based Scanning
๐ Problem: Leetcode 75 - Sort Colors
Sort an array with only 0s, 1s, and 2s in-place.
๐ง Intuition:
In this problem, we use three pointers to divide the array into regions (like the Dutch National Flag).
โ Code:
public void sortColors(int[] nums) {
int low = 0, mid = 0, high = nums.length - 1;
while (mid <= high) {
if (nums[mid] == 0) swap(nums, low++, mid++);
else if (nums[mid] == 1) mid++;
else swap(nums, mid, high--);
}
}
private void swap(int[] nums, int i, int j) {
int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp;
}
โฑ๏ธ Time: O(n) ย ย ๐ Space: O(1)
The Two Pointer Technique isnโt a single trick โ itโs a collection of elegant patterns that appear in countless problems.