Coding Interview Patterns — 20 Essential Patterns
In this tutorial, you'll learn about Coding Interview Patterns. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
Coding interview patterns are reusable solution templates that map to common problem types, enabling you to solve 90% of Technical Interview questions with just 20 core patterns. Instead of memorizing thousands of problems, learn to recognize the pattern and apply the template. DodaTech engineering uses these patterns daily — from parsing browser data streams (Sliding Window) to optimizing antivirus signature lookups (binary search).
Pattern Identification Flowchart
flowchart TD
Q["Problem Statement"] --> S{Need to
search?}
S -->|Sorted| BS["Binary Search"]
S -->|Unsorted| H{Compare pairs?}
H -->|Yes| TP["Two Pointers"]
H -->|No| SW{Contiguous
subarray?}
SW -->|Yes| SL["Sliding Window"]
SW -->|No| G{Graph or tree?}
G -->|Shortest path| BFS["BFS"]
G -->|All paths| DFS["DFS"]
G -->|Connected| UF["Union-Find"]
Q --> D{Combinations?}
D -->|Yes| BT["Backtracking"]
Q --> O{Optimization?}
O -->|Overlapping| DP["DP"]
O -->|Top K| HK["Heap"]
style BS fill:#f90,color:#fff
Pattern 1: Two Pointers
Use when: Sorted array, need to find pairs satisfying a condition.
def two_sum_sorted(nums, target):
left, right = 0, len(nums) - 1
while left < right:
current = nums[left] + nums[right]
if current == target:
return [left, right]
elif current < target:
left += 1
else:
right -= 1
return [-1, -1]
print(two_sum_sorted([2, 7, 11, 15], 9))
print(two_sum_sorted([1, 3, 5, 7, 9], 10))
Expected output:
[0, 1]
[1, 3]
Variations: Three Sum, Remove Duplicates, Container With Most Water, Trapping Rain Water.
Pattern 2: Sliding Window
Use when: Contiguous subarray/substring with a constraint.
def max_sum_subarray(nums, k):
window_sum = sum(nums[:k])
max_sum = window_sum
for i in range(k, len(nums)):
window_sum += nums[i] - nums[i - k]
max_sum = max(max_sum, window_sum)
return max_sum
print(max_sum_subarray([2, 1, 5, 1, 3, 2], 3))
print(max_sum_subarray([1, 9, -1, -2, 7, 3, -1, 2], 4))
Expected output:
9
13
Variations: Longest Substring Without Repeating, Minimum Window Substring, Permutation in String.
Pattern 3: Binary Search
Use when: Sorted array, find element or boundary.
def binary_search(nums, target):
left, right = 0, len(nums) - 1
while left <= right:
mid = left + (right - left) // 2
if nums[mid] == target:
return mid
elif nums[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1
def find_peak(nums):
left, right = 0, len(nums) - 1
while left < right:
mid = left + (right - left) // 2
if nums[mid] > nums[mid + 1]:
right = mid
else:
left = mid + 1
return left
print(f"Index of 7: {binary_search([1, 3, 5, 7, 9, 11], 7)}")
print(f"Peak at: {find_peak([1, 2, 3, 5, 4, 3, 1])}")
Expected output:
Index of 7: 3
Peak at: 3
Pattern 4: BFS
Use when: Shortest path in unweighted graph, level-order traversal.
from collections import deque
def bfs_shortest_path(graph, start, target):
visited = {start}
queue = deque([(start, 0)])
while queue:
node, distance = queue.popleft()
if node == target:
return distance
for neighbor in graph[node]:
if neighbor not in visited:
visited.add(neighbor)
queue.append((neighbor, distance + 1))
return -1
graph = {'A': ['B', 'C'], 'B': ['A', 'D', 'E'], 'C': ['A', 'F'],
'D': ['B'], 'E': ['B', 'F'], 'F': ['C', 'E']}
print(bfs_shortest_path(graph, 'A', 'F'))
Expected output:
2
Pattern 5: DFS
Use when: Exploring all paths, detecting cycles, connected components.
def num_islands(grid):
if not grid:
return 0
rows, cols = len(grid), len(grid[0])
count = 0
def dfs(r, c):
if r < 0 or r >= rows or c < 0 or c >= cols or grid[r][c] == '0':
return
grid[r][c] = '0'
dfs(r+1, c); dfs(r-1, c); dfs(r, c+1); dfs(r, c-1)
for r in range(rows):
for c in range(cols):
if grid[r][c] == '1':
count += 1
dfs(r, c)
return count
grid = [['1','1','0','0','0'],['1','1','0','0','0'],
['0','0','1','0','0'],['0','0','0','1','1']]
print(num_islands(grid))
Expected output:
3
Pattern 6: Dynamic Programming
Use when: Optimal substructure + overlapping subproblems.
def knapsack(weights, values, capacity):
n = len(weights)
dp = [[0] * (capacity + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
for w in range(capacity + 1):
if weights[i-1] <= w:
dp[i][w] = max(values[i-1] + dp[i-1][w - weights[i-1]], dp[i-1][w])
else:
dp[i][w] = dp[i-1][w]
return dp[n][capacity]
print(knapsack([2, 3, 4, 5], [3, 4, 5, 6], 5))
print(knapsack([1, 2, 3], [6, 10, 12], 5))
Expected output:
7
22
Pattern 7: Backtracking
Use when: All combinations, permutations, or subsets.
def permute(nums):
result = []
def backtrack(path, remaining):
if not remaining:
result.append(path[:])
return
for i, num in enumerate(remaining):
path.append(num)
backtrack(path, remaining[:i] + remaining[i+1:])
path.pop()
backtrack([], nums)
return result
print(permute([1, 2, 3]))
Expected output:
[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
Pattern 8: Top K (Heap)
Use when: K largest/smallest/frequent elements.
import heapq
def top_k_frequent(nums, k):
freq = {}
for num in nums:
freq[num] = freq.get(num, 0) + 1
heap = []
for num, count in freq.items():
heapq.heappush(heap, (count, num))
if len(heap) > k:
heapq.heappop(heap)
return [num for count, num in heap]
print(top_k_frequent([1, 1, 1, 2, 2, 3], 2))
print(top_k_frequent([4, 4, 4, 4, 5, 5, 5, 6, 6, 7], 3))
Expected output:
[2, 1]
[6, 5, 4]
Pattern 9: Union-Find
Use when: Dynamic connectivity, cycle detection, connected components.
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]:
self.parent[px] = py
elif self.rank[px] > self.rank[py]:
self.parent[py] = px
else:
self.parent[py] = px
self.rank[px] += 1
return True
def connected(self, x, y):
return self.find(x) == self.find(y)
uf = UnionFind(6)
for u, v in [(0, 1), (1, 2), (3, 4), (4, 5)]:
uf.union(u, v)
print(uf.connected(0, 2))
print(uf.connected(0, 3))
print(uf.connected(3, 5))
Expected output:
True
False
True
Pattern Identification Cheatsheet
| Question | Pattern |
|---|---|
| Is input sorted? | Two Pointers or Binary Search |
| Need contiguous subarray/string? | Sliding Window |
| Shortest path or level-order? | BFS |
| All paths, combinations? | Backtracking |
| Connected components? | Union-Find |
| Optimize with choices? | DP or Greedy |
| Top K elements? | Heap |
| Prefix lookups? | Trie |
Common Mistakes
- Jumping to code before pattern identification — Spend 2–3 minutes analyzing the problem. Choose your pattern before writing.
- Using DP when greedy works — Greedy is simpler. Only use DP for overlapping subproblems.
- Off-by-one in binary search — Use
left <= rightfor standard,left < rightfor boundary search. - BFS vs DFS confusion — BFS for shortest path, DFS for exploring all paths.
- Forgetting visited nodes — Unmarked visited nodes cause infinite loops.
- Backtracking without pruning — Add pruning conditions: sort first to skip duplicates, check partial validity.
- Heap direction confusion — Min heap for K largest, max heap for K smallest. Python's heapq is min heap.
Practice Questions
1. Which pattern for "Find longest substring without repeating characters"? Sliding Window — contiguous substring with a uniqueness constraint.
2. BFS vs DFS when? BFS for shortest path when all edges have equal weight. DFS for exploring all possibilities when memory is limited.
3. Time complexity of Union-Find with path compression? O(alpha(n)) — inverse Ackermann function, nearly constant for all practical inputs.
4. How to identify DP problems? Keywords: "minimum", "maximum", "number of ways". Check for optimal substructure and overlapping subproblems.
5. Challenge: Identify patterns for these problems:
- "Find all palindrome substrings" — Two pointers or DP
- "Serialize a binary tree" — BFS/DFS
- "Merge K sorted lists" — Heap (Top K)
- "Word ladder II" — BFS + Backtracking
Real-World Task
Solve 50 LeetCode problems across the 9 core patterns. For each, log the pattern you used and why. Review your log weekly to strengthen pattern recognition.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro