Stop solving problems randomly. Start recognizing patterns. Two Pointers is the most underrated pattern that appears in 100+ LeetCode problems, yet most people don't know when to use it.
After solving 500+ problems, I've broken down the Two Pointers Pattern into 5 categories that will make you spot these problems instantly in interviews.
When to use: Array/String manipulation, partition problems, palindrome checks
Template:
int left = 0, right = n - 1;
while (left < right) {
// Process based on condition
if (condition) {
// Do something
}
left++;
right--;
}Problems:
When to use: Remove duplicates, in-place modifications, linked list cycles
Template:
int slow = 0;
for (int fast = 0; fast < n; fast++) {
if (condition) {
arr[slow] = arr[fast];
slow++;
}
}Problems:
When to use: Subarray/substring problems with constraints
Template:
int left = 0;
for (int right = 0; right < n; right++) {
// Expand window
while (window_invalid) {
// Shrink window
left++;
}
// Update result
}Problems:
When to use: Merge sorted arrays, intersection problems
Template:
int i = 0, j = 0;
while (i < n && j < m) {
if (arr1[i] < arr2[j]) i++;
else if (arr1[i] > arr2[j]) j++;
else { /* found match */ i++; j++; }
}Problems:
When to use: Partitioning based on condition, Dutch National Flag
Template:
int boundary = 0;
for (int i = 0; i < n; i++) {
if (condition) {
swap(arr[i], arr[boundary]);
boundary++;
}
}Problems:
Is it about subarrays/substrings with size/sum constraints?
├─ YES → Sliding Window (Category 3)
└─ NO ↓
Do you have TWO different arrays/lists to process?
├─ YES → Merge Pattern (Category 4)
└─ NO ↓
Do you need to partition/rearrange based on condition?
├─ YES → Partition Pattern (Category 5)
└─ NO ↓
Are pointers moving TOWARD each other?
├─ YES → Opposite Direction (Category 1)
└─ NO → Same Direction / Fast-Slow (Category 2)Instant Recognition: Sorted array + pair → Opposite Direction
// Two Sum II approach
int left = 0, right = n - 1;
while (left < right) {
int sum = arr[left] + arr[right];
if (sum == target) return true;
else if (sum < target) left++;
else right--;
}Instant Recognition: In-place + modify → Same Direction (Fast-Slow)
int slow = 0;
for (int fast = 0; fast < n; fast++) {
if (arr[fast] != val) {
arr[slow++] = arr[fast];
}
}Instant Recognition: Substring + constraint → Sliding Window
unordered_map<char, int> freq;
int left = 0, maxLen = 0;
for (int right = 0; right < n; right++) {
freq[s[right]]++;
while (freq.size() > k) {
freq[s[left]]--;
if (freq[s[left]] == 0) freq.erase(s[left]);
left++;
}
maxLen = max(maxLen, right - left + 1);
}Sorted Array = Strong Two Pointers Signal
"In-Place" = Fast-Slow Pattern
Subarray/Substring = Sliding Window
Multiple Arrays = Merge Pattern
Partition/Rearrange = Quick Select Style
❌ Mistake 1: Using two pointers when you need a hash map
❌ Mistake 2: Not handling edge cases
// Always check:
if (n == 0 || n == 1) return /* base case */;❌ Mistake 3: Wrong pointer movement
❌ Mistake 4: Forgetting to validate while condition
// Always ensure valid range
while (left < right) // not left <= right for opposite direction
while (slow < n && fast < n) // for same direction| Pattern | Time | Space | Best For |
|---|---|---|---|
| Opposite Direction | O(n) | O(1) | Sorted array, palindrome |
| Same Direction | O(n) | O(1) | In-place modification |
| Sliding Window | O(n) | O(k) | Subarray with constraint |
| Merge | O(n+m) | O(1) | Two sorted arrays |
| Partition | O(n) | O(1) | Rearrange elements |
🚫 Unsorted array + need all pairs → Use Hash Map
🚫 Need to find elements in any order → Use Hash Set
🚫 Tree/Graph traversal → Use DFS/BFS
🚫 Dynamic Programming state → Use DP array
🚫 Need frequency count → Use Hash Map first
Drop your pattern recognition tips below! 👇
Google: Loves Sliding Window (40% of array problems)
Amazon: Mix of all patterns (35% two pointers)
Microsoft: Fast-Slow for in-place (30%)
Facebook: Opposite direction for optimization (45%)
If this helped you, give it an upvote! 🚀