Most coding interview questions at FAANG and top tech companies follow a small number of patterns. Analyses of real interview question sets consistently find that the vast majority — often cited as 70-90% — map to 10-12 core patterns. If you learn these patterns, you can solve most interview problems — even ones you have never seen before.
In this article, you will learn all 10 patterns with examples. We show code in Python, with key examples in Kotlin and Go.
Why Patterns Matter
Random LeetCode grinding is inefficient. You solve 300 problems and still feel stuck on new ones. The reason: you are memorizing solutions instead of learning patterns.
A pattern is a reusable approach. Once you recognize the pattern, you know the template. You adapt it to the specific problem.
Pattern 1: Two Pointers
When to use: Sorted arrays, finding pairs, removing duplicates in-place, palindrome checking.
Template: Start two pointers at opposite ends (or at the beginning for same-direction). Move them based on a condition.
Python:
# Valid Palindrome
def is_palindrome(s):
s = "".join(c.lower() for c in s if c.isalnum())
left, right = 0, len(s) - 1
while left < right:
if s[left] != s[right]:
return False
left += 1
right -= 1
return True
Key problems: Two Sum II (#167), 3Sum (#15), Container With Most Water (#11), Trapping Rain Water (#42).
Pattern 2: Sliding Window
When to use: Contiguous subarray/substring problems asking for longest, shortest, or maximum sum.
Template: Expand the window by moving the right pointer. Shrink by moving the left pointer when a condition is violated.
Python:
# Longest Repeating Character Replacement
def character_replacement(s, k):
count = {}
left = result = max_freq = 0
for right in range(len(s)):
count[s[right]] = count.get(s[right], 0) + 1
max_freq = max(max_freq, count[s[right]])
while (right - left + 1) - max_freq > k:
count[s[left]] -= 1
left += 1
result = max(result, right - left + 1)
return result
Key problems: Longest Substring Without Repeating Characters (#3), Minimum Window Substring (#76), Maximum Average Subarray (#643).
Pattern 3: Binary Search
When to use: Sorted data, search space with monotonic property, minimize maximum or maximize minimum.
Template: Define the search space, check the mid condition, narrow the space.
Kotlin:
// Find peak element (binary search on unsorted array)
fun findPeakElement(nums: IntArray): Int {
var left = 0
var right = nums.size - 1
while (left < right) {
val mid = left + (right - left) / 2
if (nums[mid] > nums[mid + 1]) right = mid
else left = mid + 1
}
return left
}
Key problems: Search in Rotated Sorted Array (#33), Koko Eating Bananas (#875), Find Peak Element (#162).
Pattern 4: BFS / DFS
When to use: Graph traversal, tree problems, grid/matrix problems, shortest path, connected components.
Template: BFS uses a queue (for shortest path). DFS uses recursion or a stack (for exploring all paths).
Go:
// Flood fill using DFS
func floodFill(image [][]int, sr, sc, color int) [][]int {
original := image[sr][sc]
if original == color {
return image
}
var dfs func(r, c int)
dfs = func(r, c int) {
if r < 0 || r >= len(image) || c < 0 || c >= len(image[0]) {
return
}
if image[r][c] != original {
return
}
image[r][c] = color
dfs(r+1, c)
dfs(r-1, c)
dfs(r, c+1)
dfs(r, c-1)
}
dfs(sr, sc)
return image
}
Key problems: Number of Islands (#200), Word Ladder (#127), Clone Graph (#133), Binary Tree Level Order Traversal (#102).
Pattern 5: Dynamic Programming
When to use: Optimization problems (min/max), counting problems (number of ways), problems with overlapping subproblems.
Template: Define state, write recurrence, identify base cases, compute bottom-up.
Python:
# Word Break
def word_break(s, word_dict):
word_set = set(word_dict)
dp = [False] * (len(s) + 1)
dp[0] = True
for i in range(1, len(s) + 1):
for j in range(i):
if dp[j] and s[j:i] in word_set:
dp[i] = True
break
return dp[len(s)]
Key problems: Climbing Stairs (#70), Coin Change (#322), Longest Increasing Subsequence (#300), Word Break (#139).
Pattern 6: Backtracking
When to use: Generate all combinations/permutations/subsets, constraint satisfaction (N-Queens, Sudoku).
Template: Choose, explore, undo.
Python:
# Letter Combinations of a Phone Number
def letter_combinations(digits):
if not digits:
return []
phone = {"2": "abc", "3": "def", "4": "ghi", "5": "jkl",
"6": "mno", "7": "pqrs", "8": "tuv", "9": "wxyz"}
result = []
def backtrack(index, path):
if index == len(digits):
result.append("".join(path))
return
for char in phone[digits[index]]:
path.append(char)
backtrack(index + 1, path)
path.pop()
backtrack(0, [])
return result
Key problems: Subsets (#78), Permutations (#46), Combination Sum (#39), N-Queens (#51).
Pattern 7: Monotonic Stack
When to use: “Next greater element,” “previous smaller element,” “largest rectangle” problems.
Template: Maintain a stack of indices. Pop elements that violate the monotonic property.
Python:
# Next Greater Element
def next_greater_element(nums):
result = [-1] * len(nums)
stack = [] # Stack of indices
for i in range(len(nums)):
while stack and nums[i] > nums[stack[-1]]:
result[stack.pop()] = nums[i]
stack.append(i)
return result
Kotlin:
fun nextGreaterElement(nums: IntArray): IntArray {
val result = IntArray(nums.size) { -1 }
val stack = ArrayDeque<Int>()
for (i in nums.indices) {
while (stack.isNotEmpty() && nums[i] > nums[stack.last()]) {
result[stack.removeLast()] = nums[i]
}
stack.addLast(i)
}
return result
}
Key problems: Daily Temperatures (#739), Largest Rectangle in Histogram (#84), Next Greater Element (#496).
Pattern 8: Top K Elements (Heap)
When to use: Finding the K largest, K smallest, K most frequent elements.
Template: Use a min-heap of size K for K largest. Use a max-heap of size K for K smallest.
Python:
import heapq
# Top K Frequent Elements
def top_k_frequent(nums, k):
from collections import Counter
count = Counter(nums)
return heapq.nlargest(k, count.keys(), key=count.get)
Go:
import "container/heap"
// MinHeap implements heap.Interface for int values.
type MinHeap []int
func (h MinHeap) Len() int { return len(h) }
func (h MinHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h MinHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *MinHeap) Push(x interface{}) { *h = append(*h, x.(int)) }
func (h *MinHeap) Pop() interface{} {
old := *h
n := len(old)
val := old[n-1]
*h = old[:n-1]
return val
}
// Kth Largest — use a min-heap of size k
func findKthLargest(nums []int, k int) int {
h := &MinHeap{}
heap.Init(h)
for _, num := range nums {
heap.Push(h, num)
if h.Len() > k {
heap.Pop(h)
}
}
return (*h)[0]
}
Key problems: Kth Largest Element (#215), Top K Frequent Elements (#347), Merge K Sorted Lists (#23).
Pattern 9: Merge Intervals
When to use: Overlapping intervals, scheduling problems, meeting rooms.
Template: Sort by start time, then iterate and merge overlapping intervals.
Python:
# Insert Interval
def insert_interval(intervals, new_interval):
result = []
for i, interval in enumerate(intervals):
if new_interval[1] < interval[0]:
result.append(new_interval)
return result + intervals[i:]
elif new_interval[0] > interval[1]:
result.append(interval)
else:
new_interval = [
min(new_interval[0], interval[0]),
max(new_interval[1], interval[1]),
]
result.append(new_interval)
return result
Key problems: Merge Intervals (#56), Insert Interval (#57), Non-overlapping Intervals (#435), Meeting Rooms II (#253).
Pattern 10: Union-Find
When to use: Dynamic connectivity, grouping, detecting cycles in undirected graphs, connected components.
Template: Two operations: find (with path compression) and union (with rank).
Python:
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
Key problems: Number of Connected Components (#323), Redundant Connection (#684), Accounts Merge (#721).
Pattern Recognition Flowchart
When you see a problem, ask these questions:
Is the input sorted (or can you sort it)?
YES -> Two Pointers or Binary Search
Does it ask for contiguous subarray/substring?
YES -> Sliding Window
Does it involve a grid, tree, or graph?
YES -> BFS (shortest) or DFS (explore all)
Does it ask for min/max/count with overlapping subproblems?
YES -> Dynamic Programming
Does it ask for all combinations/permutations?
YES -> Backtracking
Does it ask for K largest/smallest?
YES -> Heap (Top K)
Does it involve intervals?
YES -> Sort + Merge Intervals
Does it ask for "next greater/smaller"?
YES -> Monotonic Stack
Does it involve grouping or connectivity?
YES -> Union-Find
Common Mistakes
Not recognizing the pattern. Spend the first 2-3 minutes identifying the pattern before coding. If you jump straight to coding, you might pick the wrong approach.
Mixing patterns. Some problems use multiple patterns (like sorting + two pointers). Identify the primary pattern first.
Memorizing solutions instead of patterns. If you memorize “Two Sum uses a hash map,” you only solve Two Sum. If you learn “hash map for O(1) lookup to reduce O(n^2) to O(n),” you solve many problems.
Practice Plan
| Week | Pattern | Problems |
|---|---|---|
| 1 | Two Pointers + Sliding Window | 10 problems |
| 2 | Binary Search + BFS/DFS | 10 problems |
| 3 | DP + Backtracking | 10 problems |
| 4 | Monotonic Stack + Heap + Intervals + Union-Find | 10 problems |
This gives you 40 problems in 4 weeks, covering all patterns.
What’s Next?
Now that you know the patterns, the next three articles dive deeper into each category: string patterns, tree/graph patterns, and DP patterns. Start with String Manipulation Patterns.
Next: DSA Tutorial #20: String Manipulation Patterns
Full series: DSA from Zero to Interview Ready