LeetCode Patterns Cheat Sheet: The 15 Patterns I Used to Pass FAANG Interviews
After solving 400+ LeetCode problems, I realized most of them use the same 15 patterns. Learn these, and you can solve almost anything they throw at you.
When I first started grinding LeetCode, I was doing it wrong. I'd solve a problem, move on, and forget it a week later. Then I'd see a similar problem and have no idea how to approach it.
The breakthrough came when I stopped memorizing solutions and started recognizing patterns. There are really only about 15 core patterns that cover 90% of what you'll see in interviews. Learn to recognize when to apply each one, and suddenly LeetCode becomes much more manageable.
Here's my complete cheat sheet—the patterns, when to use them, and example problems for each.
How to Use This Guide
- • Read through each pattern and understand WHEN to apply it
- • Do 3-5 problems per pattern to build muscle memory
- • When you see a new problem, first identify which pattern applies
- • Review patterns weekly until they become second nature
Pattern 1: Two Pointers
Two Pointers
When to use: Sorted arrays, finding pairs, comparing elements from both ends, or partitioning.
Key insight: Use two pointers moving toward each other or in the same direction to reduce O(n²) to O(n).
// Two Sum II (sorted array)
left = 0, right = n-1
while left < right:
sum = arr[left] + arr[right]
if sum == target: return [left, right]
elif sum < target: left++
else: right--
Practice: Two Sum II, 3Sum, Container With Most Water, Trapping Rain Water
Pattern 2: Sliding Window
Sliding Window
When to use: Contiguous subarrays/substrings, finding max/min in a window, or problems mentioning "consecutive" elements.
Key insight: Expand window to include elements, shrink to maintain constraints. Track window state efficiently.
// Maximum sum subarray of size k
window_sum = sum(arr[0:k])
max_sum = window_sum
for i in range(k, n):
window_sum += arr[i] - arr[i-k] // slide window
max_sum = max(max_sum, window_sum)
Practice: Maximum Subarray, Longest Substring Without Repeating Characters, Minimum Window Substring, Sliding Window Maximum
Pattern 3: Fast & Slow Pointers
Fast & Slow Pointers (Floyd's Cycle)
When to use: Cycle detection, finding middle of linked list, or finding the start of a cycle.
Key insight: Slow moves 1 step, fast moves 2 steps. They'll meet if there's a cycle.
// Detect cycle in linked list
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast: return True // cycle exists
return False
Practice: Linked List Cycle, Find Duplicate Number, Happy Number, Middle of Linked List
Pattern 4: Merge Intervals
Merge Intervals
When to use: Overlapping intervals, scheduling problems, or finding conflicts.
Key insight: Sort by start time, then merge if current.start <= previous.end.
// Merge overlapping intervals
intervals.sort(key=lambda x: x[0])
merged = [intervals[0]]
for current in intervals[1:]:
if current[0] <= merged[-1][1]:
merged[-1][1] = max(merged[-1][1], current[1])
else:
merged.append(current)
Practice: Merge Intervals, Insert Interval, Non-overlapping Intervals, Meeting Rooms I & II
Pattern 5: Binary Search
Binary Search
When to use: Sorted arrays, finding boundaries, or when the problem has a monotonic property.
Key insight: If you can define a condition that's false for left half and true for right (or vice versa), use binary search.
// Standard binary search
left, right = 0, len(arr) - 1
while left <= right:
mid = (left + right) // 2
if arr[mid] == target: return mid
elif arr[mid] < target: left = mid + 1
else: right = mid - 1
Practice: Binary Search, Search in Rotated Sorted Array, Find First and Last Position, Koko Eating Bananas
Pattern 6: BFS (Breadth-First Search)
BFS
When to use: Shortest path in unweighted graph, level-order traversal, or finding nearest/minimum steps.
Key insight: Use a queue. Process level by level. First time you reach a node is the shortest path.
// Level order traversal
queue = deque([root])
while queue:
level_size = len(queue)
for _ in range(level_size):
node = queue.popleft()
process(node)
queue.extend(node.children)
Practice: Binary Tree Level Order Traversal, Rotting Oranges, Word Ladder, Shortest Path in Binary Matrix
Pattern 7: DFS (Depth-First Search)
DFS
When to use: Exploring all paths, finding connected components, tree traversals, or backtracking problems.
Key insight: Use recursion or explicit stack. Mark nodes as visited to avoid cycles.
// DFS on graph
def dfs(node, visited):
if node in visited: return
visited.add(node)
process(node)
for neighbor in graph[node]:
dfs(neighbor, visited)
Practice: Number of Islands, Clone Graph, Path Sum, Course Schedule (cycle detection)
Pattern 8: Backtracking
Backtracking
When to use: Finding all combinations/permutations, constraint satisfaction, or "generate all possible" problems.
Key insight: Make a choice, recurse, then undo the choice (backtrack). Prune invalid paths early.
// Generate all subsets
def backtrack(start, current):
result.append(current[:])
for i in range(start, len(nums)):
current.append(nums[i]) // make choice
backtrack(i + 1, current)
current.pop() // undo choice
Practice: Subsets, Permutations, Combination Sum, N-Queens, Sudoku Solver
Pattern 9: Dynamic Programming
Dynamic Programming
When to use: Optimization problems (min/max), counting ways, or when problem has overlapping subproblems.
Key insight: Define state, find recurrence relation, handle base cases. Build up from smaller subproblems.
// Climbing stairs (Fibonacci-like)
dp[0] = 1, dp[1] = 1
for i in range(2, n+1):
dp[i] = dp[i-1] + dp[i-2] // recurrence
return dp[n]
Practice: Climbing Stairs, House Robber, Coin Change, Longest Common Subsequence, 0/1 Knapsack
Pattern 10: Topological Sort
Topological Sort
When to use: Dependency ordering, task scheduling, or any DAG (directed acyclic graph) ordering problem.
Key insight: Use Kahn's algorithm (BFS with in-degrees) or DFS post-order. Cycle means no valid ordering.
// Kahn's Algorithm
queue = [node for node if in_degree[node] == 0]
order = []
while queue:
node = queue.pop(0)
order.append(node)
for neighbor in graph[node]:
in_degree[neighbor] -= 1
if in_degree[neighbor] == 0:
queue.append(neighbor)
Practice: Course Schedule I & II, Alien Dictionary, Task Scheduler
Pattern 11: Heap / Priority Queue
Heap / Priority Queue
When to use: Finding k largest/smallest, merging sorted lists, or scheduling by priority.
Key insight: Min-heap for k largest, max-heap for k smallest. Heap operations are O(log n).
// Find k largest elements
min_heap = []
for num in nums:
heappush(min_heap, num)
if len(min_heap) > k:
heappop(min_heap) // remove smallest
return min_heap // contains k largest
Practice: Kth Largest Element, Merge K Sorted Lists, Top K Frequent Elements, Find Median from Data Stream
Pattern 12: Union Find
Union Find (Disjoint Set)
When to use: Finding connected components, detecting cycles in undirected graphs, or grouping elements.
Key insight: Path compression + union by rank makes operations nearly O(1).
// Union Find with path compression
def find(x):
if parent[x] != x:
parent[x] = find(parent[x]) // path compression
return parent[x]
def union(x, y):
px, py = find(x), find(y)
if px != py: parent[px] = py
Practice: Number of Connected Components, Redundant Connection, Accounts Merge, Longest Consecutive Sequence
Pattern 13: Trie
Trie (Prefix Tree)
When to use: Prefix matching, autocomplete, word search, or storing a dictionary of words.
Key insight: Each node represents a character. Path from root to node forms a prefix.
// Trie Node
class TrieNode:
children = {}
is_end = False
def insert(word):
node = root
for char in word:
if char not in node.children:
node.children[char] = TrieNode()
node = node.children[char]
node.is_end = True
Practice: Implement Trie, Word Search II, Design Add and Search Words, Replace Words
Pattern 14: Monotonic Stack
Monotonic Stack
When to use: Next greater/smaller element, histogram problems, or maintaining increasing/decreasing order.
Key insight: Keep stack in sorted order. Pop elements that violate the order.
// Next greater element
stack = []
result = [-1] * n
for i in range(n):
while stack and nums[i] > nums[stack[-1]]:
idx = stack.pop()
result[idx] = nums[i]
stack.append(i)
Practice: Next Greater Element, Daily Temperatures, Largest Rectangle in Histogram, Trapping Rain Water
Pattern 15: Bit Manipulation
Bit Manipulation
When to use: Finding single numbers, power of 2, counting bits, or XOR problems.
Key insight: XOR with itself = 0. XOR with 0 = itself. AND with (n-1) removes rightmost set bit.
// Common operations
x & (x-1) // remove rightmost set bit
x & (-x) // isolate rightmost set bit
x ^ x = 0 // number XOR itself is 0
x ^ 0 = x // number XOR 0 is itself
Practice: Single Number, Number of 1 Bits, Counting Bits, Missing Number, Power of Two
Practice Coding Patterns with AI Mock Interviews
Knowing patterns is half the battle. Applying them under pressure is the other half. LastRound AI offers AI mock interviews and a coding question bank to help you practice identifying the right pattern and implementing solutions under timed conditions.
Pattern Recognition Cheat Sheet
Quick Pattern Identification
"Contiguous subarray" → Sliding Window
"Sorted array + find pair" → Two Pointers
"Shortest path" → BFS
"All possible combinations" → Backtracking
"Min/max optimization" → Dynamic Programming
"K largest/smallest" → Heap
"Connected components" → Union Find or DFS
"Dependency order" → Topological Sort
"Prefix matching" → Trie
"Next greater element" → Monotonic Stack
"Cycle detection" → Fast & Slow Pointers
"Overlapping intervals" → Merge Intervals
My Study Plan
Here's how I'd approach learning these patterns if I were starting over:
- Week 1-2: Two Pointers, Sliding Window, Binary Search (foundational)
- Week 3-4: BFS, DFS, Backtracking (graph/tree basics)
- Week 5-6: Dynamic Programming (the hardest but most important)
- Week 7-8: Heap, Trie, Union Find, Topological Sort (advanced)
Do 3-5 problems per pattern. Focus on understanding WHEN to apply each pattern, not just how. When you see a new problem, your first thought should be "which pattern does this match?"
