Two Pointers & Sliding Window
These two patterns appear in a huge portion of LeetCode medium problems. Once you recognize them, many problems become mechanical.
Two Pointers
Use two index variables that move toward each other (or in the same direction) to avoid nested loops.
When to use: Sorted arrays, pair-sum problems, palindrome checks, in-place operations.
Classic: Two Sum II (sorted array)
def two_sum(nums, target):
left, right = 0, len(nums) - 1
while left < right:
s = nums[left] + nums[right]
if s == target:
return [left + 1, right + 1]
elif s < target:
left += 1
else:
right -= 1
Time: O(n) — one pass. Space: O(1).
Classic: Valid Palindrome
def is_palindrome(s):
left, right = 0, len(s) - 1
while left < right:
if s[left] != s[right]:
return False
left += 1
right -= 1
return True
Classic: Container With Most Water
Move the pointer with the shorter wall inward — you can only gain by finding something taller.
def max_area(height):
left, right = 0, len(height) - 1
best = 0
while left < right:
best = max(best, min(height[left], height[right]) * (right - left))
if height[left] < height[right]:
left += 1
else:
right -= 1
return best
Sliding Window
Maintain a window [left, right] over an array/string, expanding right and shrinking left to satisfy a constraint.
When to use: Subarray/substring problems with a size or frequency constraint.
Fixed-size window: Max Sum Subarray of Size K
def max_sum(nums, k):
window = sum(nums[:k])
best = window
for i in range(k, len(nums)):
window += nums[i] - nums[i - k]
best = max(best, window)
return best
Variable-size window: Longest Substring Without Repeating Characters
def length_of_longest_substring(s):
seen = {}
left = best = 0
for right, ch in enumerate(s):
if ch in seen and seen[ch] >= left:
left = seen[ch] + 1
seen[ch] = right
best = max(best, right - left + 1)
return best
Variable-size window: Minimum Window Substring
from collections import Counter
def min_window(s, t):
need = Counter(t)
missing = len(t)
left = start = end = 0
for right, ch in enumerate(s, 1):
if need[ch] > 0:
missing -= 1
need[ch] -= 1
if missing == 0:
while need[s[left]] < 0:
need[s[left]] += 1
left += 1
if end == 0 or right - left < end - start:
start, end = left, right
need[s[left]] += 1
missing += 1
left += 1
return s[start:end]
Pattern Recognition Cheat Sheet
| Signal in problem | Pattern |
|---|---|
| "sorted array", "pair that sums to" | Two pointers (opposite ends) |
| "in-place", "remove duplicates" | Two pointers (same direction / fast-slow) |
| "longest/shortest subarray/substring" | Sliding window |
| "subarray with sum = k" | Sliding window or prefix sum |
| "linked list cycle" | Fast/slow pointers |
Practice Problems (LeetCode)
Two Pointers
- [167] Two Sum II
- [15] 3Sum
- [11] Container With Most Water
- [42] Trapping Rain Water (hard)
Sliding Window
- [3] Longest Substring Without Repeating Characters
- [76] Minimum Window Substring (hard)
- [239] Sliding Window Maximum (hard)
- [438] Find All Anagrams in a String