The 18 DSA patterns¶
Each pattern has trigger signals, a template and 10–15 essential problems. Big Tech coding rounds (and some lab screens) test whether you can recognize the pattern in a new problem within a minute and then code it cleanly under time pressure; this list trains the first skill and the 12-week plan trains the second.
Pattern 1: Two Pointers¶
Trigger signals¶
- Sorted array + finding pair/triplet
- Comparing/merging two sequences
- Palindrome check
- "Container with most water" style problems
Template¶
left, right = 0, len(arr) - 1
while left < right:
if condition_met(arr[left], arr[right]):
# process
left += 1
right -= 1
elif need_larger(arr[left] + arr[right]):
left += 1
else:
right -= 1
Essential problems (LC numbers)¶
- 1 Two Sum (easy — hashmap variant)
- 167 Two Sum II Sorted Array
- 15 3Sum
- 11 Container With Most Water
- 42 Trapping Rain Water
- 75 Sort Colors
- 125 Valid Palindrome
- 26 Remove Duplicates from Sorted Array
- 88 Merge Sorted Array
- 283 Move Zeroes
Pattern 2: Sliding Window¶
Trigger signals¶
- Substring or subarray problem
- "Longest/shortest with condition"
- Fixed-size or variable-size window
Template (variable window)¶
left = 0
result = 0
state = {} # or counter, sum, etc.
for right in range(len(arr)):
# expand window: add arr[right] to state
update_state(state, arr[right])
while window_invalid(state):
# shrink window from left
update_state(state, arr[left], remove=True)
left += 1
result = max(result, right - left + 1)
Essential problems¶
- 3 Longest Substring Without Repeating Characters
- 76 Minimum Window Substring
- 209 Minimum Size Subarray Sum
- 567 Permutation in String
- 424 Longest Repeating Character Replacement
- 30 Substring with Concatenation of All Words (hard)
- 239 Sliding Window Maximum (uses deque)
- 1004 Max Consecutive Ones III
- 1438 Longest Subarray Absolute Diff
- 2461 Maximum Sum of Distinct Subarrays With Length K
Pattern 3: Binary Search¶
Trigger signals¶
- Sorted (or partially sorted) array
- "Find target" or "find boundary"
- Need O(log n)
Template (canonical)¶
left, right = 0, len(arr) - 1
while left <= right:
mid = left + (right - left) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1
Essential problems¶
- 704 Binary Search
- 35 Search Insert Position
- 278 First Bad Version
- 374 Guess Number Higher or Lower
Pattern 4: Modified Binary Search (on answer space, on rotated arrays)¶
Trigger signals¶
- "Smallest X such that Y" → binary search on X
- Rotated sorted array
- Find peak / find boundary
Template (binary search on answer)¶
def can_achieve(value):
# returns True if value is achievable
...
left, right = min_possible, max_possible
while left < right:
mid = left + (right - left) // 2
if can_achieve(mid):
right = mid
else:
left = mid + 1
return left
Essential problems¶
- 33 Search in Rotated Sorted Array
- 153 Find Minimum in Rotated Sorted Array
- 162 Find Peak Element
- 875 Koko Eating Bananas
- 1011 Capacity to Ship Packages
- 410 Split Array Largest Sum (hard)
- 4 Median of Two Sorted Arrays (hard)
- 1539 Kth Missing Positive Number
- 2563 Count the Number of Fair Pairs
- 1268 Search Suggestions System
Pattern 5: Cyclic Sort¶
Trigger signals¶
- Array of N integers in range [1, N] or [0, N-1]
- Find missing / duplicate / kth
Template¶
i = 0
while i < len(nums):
correct_pos = nums[i] - 1
if 0 <= correct_pos < len(nums) and nums[i] != nums[correct_pos]:
nums[i], nums[correct_pos] = nums[correct_pos], nums[i]
else:
i += 1
Essential problems¶
- 268 Missing Number
- 448 Find All Numbers Disappeared in an Array
- 41 First Missing Positive (hard)
- 442 Find All Duplicates in an Array
- 287 Find the Duplicate Number
Pattern 6: In-place Linked List Reversal¶
Trigger signals¶
- Reverse linked list (whole or part)
- Reorder list
- Detect cycle / find middle
Template¶
def reverse(head):
prev, curr = None, head
while curr:
nxt = curr.next
curr.next = prev
prev = curr
curr = nxt
return prev
Essential problems¶
- 206 Reverse Linked List
- 92 Reverse Linked List II
- 25 Reverse Nodes in K-Group (hard)
- 234 Palindrome Linked List
- 143 Reorder List
- 141 Linked List Cycle
- 142 Linked List Cycle II
- 160 Intersection of Two Linked Lists
- 21 Merge Two Sorted Lists
- 23 Merge K Sorted Lists (hard)
Pattern 7: Tree BFS (level-order traversal)¶
Trigger signals¶
- "Level by level"
- Shortest path in tree
- Right-side / left-side view
Template¶
from collections import deque
queue = deque([root])
while queue:
level_size = len(queue)
for _ in range(level_size):
node = queue.popleft()
# process node
if node.left: queue.append(node.left)
if node.right: queue.append(node.right)
Essential problems¶
- 102 Binary Tree Level Order Traversal
- 199 Binary Tree Right Side View
- 103 Zigzag Level Order Traversal
- 116 Populating Next Right Pointers
- 314 Vertical Order Traversal
- 297 Serialize and Deserialize Binary Tree (hard)
Pattern 8: Tree DFS¶
Trigger signals¶
- Path problems
- Tree structure / construction
- Validation problems
- Lowest Common Ancestor (LCA)
Template (recursive)¶
def dfs(node):
if not node:
return base_case
left = dfs(node.left)
right = dfs(node.right)
return combine(node.val, left, right)
Essential problems¶
- 104 Maximum Depth of Binary Tree
- 100 Same Tree
- 226 Invert Binary Tree
- 110 Balanced Binary Tree
- 543 Diameter of Binary Tree
- 124 Binary Tree Maximum Path Sum (hard)
- 236 Lowest Common Ancestor
- 98 Validate BST
- 230 Kth Smallest in BST
- 105 Construct Tree from Preorder and Inorder
- 297 Serialize and Deserialize (hard)
- 437 Path Sum III
Pattern 9: Graph BFS / DFS / Topological Sort¶
Trigger signals¶
- Adjacency list/matrix
- Shortest path (BFS)
- Connected components
- Cycle detection
- Course scheduling / dependency order
Templates¶
# BFS
visited = set([start])
queue = deque([start])
while queue:
node = queue.popleft()
# process
for neighbor in graph[node]:
if neighbor not in visited:
visited.add(neighbor)
queue.append(neighbor)
# Topo sort (Kahn's algorithm)
in_degree = {n: 0 for n in nodes}
for u, v in edges:
in_degree[v] += 1
queue = deque([n for n in nodes if in_degree[n] == 0])
order = []
while queue:
n = queue.popleft()
order.append(n)
for nbr in graph[n]:
in_degree[nbr] -= 1
if in_degree[nbr] == 0:
queue.append(nbr)
Essential problems¶
- 200 Number of Islands
- 695 Max Area of Island
- 994 Rotting Oranges
- 207 Course Schedule (cycle detection)
- 210 Course Schedule II (topo sort)
- 269 Alien Dictionary (hard, topo)
- 743 Network Delay Time (Dijkstra)
- 787 Cheapest Flights Within K Stops (Bellman-Ford)
- 130 Surrounded Regions
- 417 Pacific Atlantic Water Flow
- 547 Number of Provinces
- 1971 Find if Path Exists in Graph
Pattern 10: Backtracking¶
Trigger signals¶
- Generate all combinations/permutations/subsets
- Constraint satisfaction (N-queens, Sudoku)
- Path finding with all paths
Template¶
def backtrack(state, choices):
if is_solution(state):
result.append(state.copy())
return
for choice in choices:
if valid(choice, state):
state.append(choice) # make choice
backtrack(state, remaining_choices(choices, choice))
state.pop() # undo choice
Essential problems¶
- 46 Permutations
- 47 Permutations II (with duplicates)
- 78 Subsets
- 90 Subsets II
- 39 Combination Sum
- 40 Combination Sum II
- 17 Letter Combinations of a Phone Number
- 22 Generate Parentheses
- 51 N-Queens (hard)
- 79 Word Search
- 131 Palindrome Partitioning
Pattern 11: Greedy¶
Trigger signals¶
- "Find optimal" where local choices work
- Interval scheduling
- Jump game style
Essential problems¶
- 55 Jump Game
- 45 Jump Game II
- 122 Best Time to Buy and Sell Stock II
- 134 Gas Station
- 435 Non-overlapping Intervals
- 56 Merge Intervals (also intervals pattern)
- 763 Partition Labels
- 1029 Two City Scheduling
- 252 Meeting Rooms
- 253 Meeting Rooms II
Pattern 12: Two Heaps¶
Trigger signals¶
- Running median
- Top-K problems with two groups
Template¶
import heapq
small = [] # max heap (negate values)
large = [] # min heap
def add(num):
if not small or num <= -small[0]:
heapq.heappush(small, -num)
else:
heapq.heappush(large, num)
rebalance()
def median():
if len(small) > len(large):
return -small[0]
return (-small[0] + large[0]) / 2
Essential problems¶
- 295 Find Median from Data Stream
- 480 Sliding Window Median
- 502 IPO (hard)
Pattern 13: Subsets / Combinations / Top-K¶
Trigger signals¶
- "Top K", "Kth largest", "K most frequent"
- Generate combinations of length K
Essential problems¶
- 215 Kth Largest Element in Array
- 347 Top K Frequent Elements
- 692 Top K Frequent Words
- 973 K Closest Points to Origin
- 658 Find K Closest Elements
Pattern 14: K-way Merge¶
Trigger signals¶
- Merge K sorted lists/arrays
- Kth smallest in matrix
Essential problems¶
- 23 Merge K Sorted Lists (hard)
- 378 Kth Smallest Element in a Sorted Matrix
- 632 Smallest Range Covering Elements from K Lists (hard)
- 373 Find K Pairs with Smallest Sums
Pattern 15: Dynamic Programming (1D)¶
Trigger signals¶
- "Number of ways"
- "Min/max cost"
- Overlapping subproblems
Essential problems¶
- 70 Climbing Stairs
- 198 House Robber
- 213 House Robber II
- 91 Decode Ways
- 322 Coin Change
- 300 Longest Increasing Subsequence
- 139 Word Break
- 152 Maximum Product Subarray
- 53 Maximum Subarray
- 121 Best Time to Buy/Sell Stock
- 740 Delete and Earn
Pattern 16: Dynamic Programming (2D / sequences)¶
Trigger signals¶
- Two strings or two sequences
- Grid problems
- "Edit distance" / "LCS" style
Essential problems¶
- 1143 Longest Common Subsequence
- 72 Edit Distance (hard)
- 10 Regular Expression Matching (hard)
- 44 Wildcard Matching (hard)
- 62 Unique Paths
- 64 Minimum Path Sum
- 221 Maximal Square
- 5 Longest Palindromic Substring
- 516 Longest Palindromic Subsequence
- 354 Russian Doll Envelopes (hard)
- 718 Maximum Length of Repeated Subarray
- 312 Burst Balloons (hard, interval DP)
Pattern 17: Tries¶
Trigger signals¶
- Prefix matching
- Word search problems
- Autocomplete
Template¶
class Trie:
def __init__(self):
self.children = {}
self.is_end = False
def insert(self, word):
node = self
for ch in word:
if ch not in node.children:
node.children[ch] = Trie()
node = node.children[ch]
node.is_end = True
Essential problems¶
- 208 Implement Trie
- 211 Design Add and Search Words (with wildcards)
- 212 Word Search II (hard; trie + backtracking)
- 1268 Search Suggestions System
- 648 Replace Words
Pattern 18: Union Find (Disjoint Set Union)¶
Trigger signals¶
- Connected components dynamically
- "Find if two nodes connected"
- Counting components
Template¶
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]) # path compression
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
Essential problems¶
- 547 Number of Provinces
- 200 Number of Islands (can be done with UF)
- 684 Redundant Connection
- 1319 Number of Operations to Make Network Connected
- 990 Satisfiability of Equality Equations
- 721 Accounts Merge
How to use this list¶
Per-pattern study (weeks 1–9 of the plan)¶
- Read the pattern description + template
- Solve 3-5 problems in order of difficulty
- After each problem, articulate WHY this pattern applied
- Move to the next pattern only when you can recognize problems in <60 seconds
Cross-pattern mixing (weeks 10–12, then maintenance)¶
- Use LeetCode's random function within a difficulty
- Or use Blind 75 / NeetCode 150 mixed lists
- For each problem, identify pattern FIRST, then code
A 12-week plan for people with full-time jobs¶
About 4 hours a week: two weekday evenings of an hour each (two problems per evening) and one weekend block of 1.5–2 hours (four problems plus a review of everything you missed). That is roughly 8 problems a week and about 100 in total, which is enough to recognize every pattern when you see it.
| Week | Patterns | Problems | Goal by the end of the week |
|---|---|---|---|
| 1 | Two pointers, sliding window | 8 | Name the pattern from the problem statement alone |
| 2 | Binary search, modified binary search | 8 | Binary search on the answer space without off-by-one errors |
| 3 | Cyclic sort, in-place linked-list reversal | 8 | Pointer manipulation drawn on paper first, then coded |
| 4 | Tree BFS, tree DFS | 8 | Recursive and iterative versions of each |
| 5 | Graph BFS/DFS/topological sort, union find | 8 | Build the graph from raw input quickly |
| 6 | Backtracking; subsets, combinations and top-K | 8 | State the search tree and its pruning before coding |
| 7 | Two heaps, k-way merge | 8 | Know heapq by heart, including tuples as keys |
| 8 | Greedy, tries | 8 | Argue why the greedy choice is safe |
| 9 | Dynamic programming, 1D and 2D | 10 | Write the recurrence and base cases before any code |
| 10 | Mixed, timed: two mediums in 45 minutes | 8 | Finish both, tested, inside the time |
| 11 | Mixed, weighted towards your weakest patterns from the log | 8 | No pattern with a first-try pass rate under 50% |
| 12 | Two full mock interviews plus company-tagged sets | 6 | Talk through your approach while you code |
Keep a one-line log per problem: pattern, minutes taken, passed first try or not, and what blocked you. The log decides week 11.
Tip
After week 12, maintain with three or four problems a week, timed. Pattern recognition decays within about a month without practice, and a final-round loop can arrive at short notice.
Time investment¶
| Phase | Activity | Total problems |
|---|---|---|
| Pattern learning (weeks 1–9) | Two patterns a week, 4–5 problems each | about 75 |
| Mixed, timed practice (weeks 10–12) | Two mediums in 45 minutes, mocks | about 25 |
| Maintenance (after week 12) | Three or four a week, timed, company-tagged | 50–150 over the following year |
For roles that weigh DSA heavily (most Big Tech loops), extend weeks 1–9 to 10–15 problems per pattern: about 250 problems in all.
Next: coding-interviews.md