Loading W Code...
Master the art of O(n) optimization with pointer tricks.
The Two Pointer Technique is an algorithmic pattern that uses two distinct indices (pointers) to traverse a data structure (typically an array or list) in O(n) time complexity. It is primarily used to minimize nested loops by moving pointers towards each other or in the same direction based on specific conditions, effectively optimizing brute-force solutions.
Expert Note: Senior Engineers at Google and Meta frequently ask Two Pointer questions (like 3Sum and Container With Most Water) to test a candidate's ability to optimize brute-force O(n²) solutions into linear O(n) solutions.
7
Patterns
45
Minutes
O(n)
Complexity
3
Visualizers
Real-life Analogy:
Imagine two friends looking for a book in a library row:
- Rahul starts from the left (start).
- Priya starts from the right (end).
They walk towards each other. If the total pages they see is too high, Priya moves left. If too low, Rahul moves right.
When to Use:
- ✅ Sorted Array problems (Find pairs, triplets)
- ✅ Searching from both ends (Palindrome, Trap Rain Water)
- ✅ Cycle detection (Linked List)
- ✅ Partitioning / Merging (QuickSort, MergeSort)
Three Main Types:
1. Opposite Direction: One from start, one from end (Meet in middle)
2. Same Direction: Both move forward (Fast/Slow pattern)
3. Sliding Window: Maintaining a "window" of elements
// Generic Structure
int left = 0;
int right = n - 1;
while (left < right) {
if (condition) {
// success
} else if (too_small) {
left++;
} else {
right--;
}
}Template (Two Sum Sorted):
left at 0, right at n-1.
- Sum < Target? Need bigger val → left++
- Sum > Target? Need smaller val → right--
- Sum == Target? Found it!
// Finding pair that sums to target in Sorted Array
int left = 0, right = nums.size() - 1;
while (left < right) {
int sum = nums[left] + nums[right];
if (sum == target) return {left, right};
else if (sum < target) left++; // Need bigger sum
else right--; // Need smaller sum
}Logic:
- Reader Pointer (i): Scans every element.
- Writer Pointer (j): Only moves when we "keep" an element.
Example: Remove Duplicates
Only write nums[i] to nums[j] if it's unique. Then increment j.
// Remove Duplicates
int j = 1; // Writer (starts at 1 because index 0 is always unique)
for (int i = 1; i < nums.size(); i++) { // Reader
if (nums[i] != nums[i-1]) {
nums[j] = nums[i];
j++;
}
}
return j; // New lengthLogic:
- Slow: Moves 1 step.
- Fast: Moves 2 steps.
- If there is a cycle, Fast will eventually catch valid Slow!
- If Fast reaches NULL, there is no cycle.
// Detect Cycle in Linked List
ListNode *slow = head, *fast = head;
while (fast && fast->next) {
slow = slow->next; // 1 step
fast = fast->next->next; // 2 steps
if (slow == fast) return true; // Collision = Cycle!
}
return false;Optimization:
Instead of recalculating the sum for every window (O(n*k)), we SLIDE:
1. Subtract the element leaving the window.
2. Add the element entering the window.
This makes it O(1) per step!
Template:
1. Compute sum of first K elements.
2. Loop from K to n.
3. Update sum: sum += arr[i] - arr[i-K]
// Max Sum Subarray of size K
int currentSum = 0;
// 1. Init first window
for (int i=0; i<K; i++) currentSum += arr[i];
int maxSum = currentSum;
// 2. Slide
for (int i=K; i<arr.size(); i++) {
currentSum += arr[i] - arr[i-K]; // Add new, Drop old
maxSum = max(maxSum, currentSum);
}
return maxSum;Template:
1. Expand Right: Add elements to window.
2. Shrink Left: While condition is met (or violated), remove elements from left to optimize.
Useful For:
- Subarray with given sum
- Longest substring with no repeats
- Minimum window substring
// Smallest Subarray with sum >= target
int left = 0, sum = 0, minLen = INT_MAX;
for (int right = 0; right < n; right++) {
sum += arr[right]; // Expand
while (sum >= target) { // Shrink
minLen = min(minLen, right - left + 1);
sum -= arr[left];
left++;
}
}
return minLen;1. Two Pointers (Opposite)
- Clue: "Sorted Array", "Pairs", "Target Sum", "Palindrome"
- Action: left = 0, right = n-1
2. Two Pointers (Same Direction)
- Clue: "In-place Remove", "Filter", "Order matters", "Merge Sorted"
- Action: Read pointer + Write pointer
3. Sliding Window (Fixed)
- Clue: "Subarray of size K", "Continuous block of K"
- Action: Build K sum, then add new/remove old.
4. Sliding Window (Variable)
- Clue: "Longest Substring", "Minimum Subarray", "Consecutive elements summing to X"
- Action: Expand Right, Shrink Left loop.
// Quick Decision Checklist
if (Input is Sorted && Find Pair) -> Two Pointers (Opposite)
if (Find Subarray of Size K) -> Sliding Window (Fixed)
if (Find Longest/Shortest Subarray) -> Sliding Window (Variable)
if (Cycle Detection) -> Fast & SlowUse Sliding Window when dealing with subarrays (contiguous elements) of size K or finding the longest/shortest substring meeting a condition. Use Two Pointers when the array is sorted (finding pairs) or when comparing elements from both ends (palindromes).
Mostly yes, for finding pairs (like Two Sum). However, for techniques like "Move Zeroes" or "Remove Duplicates" (Writer/Reader pointers) or Linked List cycles (Fast and Slow), sorting is not required.
The time complexity is O(n) (Linear Time). Although there might be nested loops (like the `while` loop for shrinking), each element is added once and removed at most once, resulting in `2n` operations in the worst case, which simplifies to O(n).