Every coding interview question is a variation of a pattern you've seen before.
After studying 500+ LeetCode problems, I distilled them into 50 patterns. Here are the 10 most powerful ones — they cover ~80% of what you'll see at FAANG interviews.
1. Sliding Window
When to use: Subarray/substring problems with a constraint (sum, length, unique chars).
def max_sum_subarray(arr, k):
window_sum = sum(arr[:k])
max_sum = window_sum
for i in range(k, len(arr)):
window_sum += arr[i] - arr[i - k]
max_sum = max(max_sum, window_sum)
return max_sum
Complexity: O(n) time, O(1) space
Classic problems: Maximum subarray of size K, Longest substring without repeating characters, Minimum window substring
2. Two Pointers
When to use: Sorted arrays, pair/triplet finding, palindrome checks.
def two_sum_sorted(arr, target):
left, right = 0, len(arr) - 1
while left < right:
curr = arr[left] + arr[right]
if curr == target:
return [left, right]
elif curr < target:
left += 1
else:
right -= 1
return []
Complexity: O(n) time, O(1) space
Classic problems: Two Sum II, 3Sum, Container With Most Water, Trapping Rain Water
3. Fast & Slow Pointers (Floyd's)
When to use: Cycle detection, finding middle of linked list, happy numbers.
def has_cycle(head):
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
return True
return False
Complexity: O(n) time, O(1) space
Classic problems: Linked List Cycle, Find the Duplicate Number, Middle of Linked List
4. Binary Search (Beyond Sorted Arrays)
When to use: Any problem where you can eliminate half the search space.
def search_rotated(nums, target):
lo, hi = 0, len(nums) - 1
while lo <= hi:
mid = (lo + hi) // 2
if nums[mid] == target:
return mid
if nums[lo] <= nums[mid]:
if nums[lo] <= target < nums[mid]:
hi = mid - 1
else:
lo = mid + 1
else:
if nums[mid] < target <= nums[hi]:
lo = mid + 1
else:
hi = mid - 1
return -1
Key insight: Binary search works on ANY monotonic function, not just sorted arrays.
Classic problems: Search in Rotated Array, Find Peak Element, Koko Eating Bananas
5. BFS/DFS on Trees
When to use: Tree traversal, level-order processing, path problems.
from collections import deque
def level_order(root):
if not root:
return []
result, queue = [], deque([root])
while queue:
level = []
for _ in range(len(queue)):
node = queue.popleft()
level.append(node.val)
if node.left: queue.append(node.left)
if node.right: queue.append(node.right)
result.append(level)
return result
Decision guide:
- Need level info? → BFS
- Need path from root? → DFS
- Need shortest path? → BFS
6. Backtracking
When to use: Generate all combinations, permutations, or valid configurations.
def subsets(nums):
result = []
def backtrack(start, current):
result.append(current[:])
for i in range(start, len(nums)):
current.append(nums[i])
backtrack(i + 1, current)
current.pop()
backtrack(0, [])
return result
Template: Choose → Explore → Unchoose
Classic problems: Subsets, Permutations, N-Queens, Word Search, Combination Sum
7. Dynamic Programming (Bottom-Up)
When to use: Overlapping subproblems + optimal substructure.
def coin_change(coins, amount):
dp = [float('inf')] * (amount + 1)
dp[0] = 0
for coin in coins:
for x in range(coin, amount + 1):
dp[x] = min(dp[x], dp[x - coin] + 1)
return dp[amount] if dp[amount] != float('inf') else -1
Decision flowchart:
- Can I define
dp[i]? → What does it represent? - What's the recurrence? →
dp[i] = f(dp[i-1], dp[i-2], ...) - What's the base case? →
dp[0] = ? - What's the iteration order? → left-to-right? 2D?
8. Monotonic Stack
When to use: "Next greater/smaller element" problems.
def next_greater_element(nums):
result = [-1] * len(nums)
stack = []
for i, num in enumerate(nums):
while stack and nums[stack[-1]] < num:
result[stack.pop()] = num
stack.append(i)
return result
Complexity: O(n) — each element pushed/popped at most once
Classic problems: Next Greater Element, Daily Temperatures, Largest Rectangle in Histogram
9. Union-Find (Disjoint Set)
When to use: Connected components, cycle detection in undirected graphs.
class UnionFind:
def __init__(self, n):
self.parent = list(range(n))
self.rank = [0] * n
def find(self, x):
if self.parent[x] != x:
self.parent[x] = self.find(self.parent[x])
return self.parent[x]
def union(self, x, y):
px, py = self.find(x), self.find(y)
if px == py:
return False
if self.rank[px] < self.rank[py]:
px, py = py, px
self.parent[py] = px
if self.rank[px] == self.rank[py]:
self.rank[px] += 1
return True
Complexity: O(α(n)) per operation ≈ O(1) amortized
Classic problems: Number of Islands, Accounts Merge, Redundant Connection
10. Topological Sort
When to use: Dependency ordering, course scheduling, build systems.
from collections import deque, defaultdict
def topo_sort(n, edges):
graph = defaultdict(list)
in_degree = [0] * n
for u, v in edges:
graph[u].append(v)
in_degree[v] += 1
queue = deque(i for i in range(n) if in_degree[i] == 0)
order = []
while queue:
node = queue.popleft()
order.append(node)
for neighbor in graph[node]:
in_degree[neighbor] -= 1
if in_degree[neighbor] == 0:
queue.append(neighbor)
return order if len(order) == n else []
Complexity: O(V + E)
Classic problems: Course Schedule, Alien Dictionary, Task Scheduler (with dependencies)
The Other 40 Patterns
These 10 cover ~80% of interviews. The remaining 40 patterns cover the other 20% — including:
- Trie for prefix matching
- Segment Tree for range queries
- Bit Manipulation tricks
- Greedy strategies with proofs
- Graph algorithms (Dijkstra, Bellman-Ford, Floyd-Warshall)
- String patterns (KMP, Rabin-Karp, Z-algorithm)
- Heap/Priority Queue patterns
- Interval merging and scheduling
- And 32 more...
Each pattern includes:
- ✅ When to recognize it
- ✅ Decision flowchart
- ✅ Code template (Python + JavaScript)
- ✅ Complexity analysis
- ✅ 3-5 classic problems with solutions
👉 Get the full 50-pattern cheat sheet →
More Interview Resources
- 🏗️ System Design Interview Cheat Sheet — 40 patterns + 8 mini-designs
- 💻 Frontend Interview Prep Kit — DOM, React, CSS, A11y
- 📋 SQL Query Cookbook — 60 ready-to-use recipes
🏦 Building something? Check out DonFlow — a zero-backend budget tracker that runs entirely in your browser.
Top comments (0)