DSA Patterns β Complete Study Guide¶
A comprehensive reference for identifying, understanding, and applying common DSA patterns in coding interviews.
How to Identify & Apply Patterns¶
| Signal in the problem | Likely pattern |
|---|---|
| Sorted array, find pair/triplet | Two Pointers |
| Cycle detection in list/array | Fast & Slow Pointers |
| Contiguous subarray, substring of size k | Sliding Window |
| "Maximum/minimum subarray sum" | Kadane's Algorithm |
| Running sum, divisibility, range queries | Prefix Sum |
| Overlapping ranges, scheduling | Merge Intervals |
| Reverse part of a linked list | In-place Reversal |
| Top/bottom K elements, median | Heap / Priority Queue |
| "How many ways", overlapping subproblems | Dynamic Programming |
| Level-by-level tree traversal | BFS / Tree Level Order |
| All combinations / permutations / subsets | Backtracking |
| Binary search on a sorted or "monotone" space | Binary Search |
| Shortest path in unweighted graph | BFS on Graph |
| Shortest path in weighted graph | Dijkstra / Bellman-Ford |
| Detect cycle in directed graph | DFS + Topological Sort |
| Repeated lookups, anagram checks | HashMap / HashSet |
| Parentheses matching, next greater element | Stack |
| Prefix matching on strings | Trie |
| Connectivity / grouping / components | Union-Find |
1. Two Pointers¶
When to use: Sorted array or linked list. You need to find a pair, triplet, or partition elements with O(1) extra space.
Core technique: Start one pointer at the left (i = 0) and one at the right (j = n-1). Move them toward each other based on a comparison.
Template:
left, right = 0, len(arr) - 1
while left < right:
if condition(arr[left], arr[right]):
# found answer
elif arr[left] + arr[right] < target:
left += 1
else:
right -= 1
| Question | Difficulty | Link |
|---|---|---|
| Pair with Target Sum | Easy | LeetCode |
| Rearrange 0s and 1s | Easy | GFG |
| Remove Duplicates from Sorted Array | Easy | LeetCode |
| Remove Duplicates II | Medium | LeetCode |
| Squaring a Sorted Array | Easy | LeetCode |
| Triplet Sum to Zero (3Sum) | Medium | LeetCode |
| Triplet Sum Closest to Target | Medium | LeetCode |
| Triplets with Smaller Sum | Medium | GFG |
| Subarray Product Less Than K | Medium | LeetCode |
| Dutch National Flag (Sort Colors) | Medium | LeetCode |
| Quadruple Sum to Target (4Sum) | Medium | LeetCode |
| Backspace String Compare | Medium | LeetCode |
| Minimum Window Sort | Medium | LeetCode |
2. Fast & Slow Pointers¶
When to use: Cycle detection in linked lists or arrays. Finding the middle of a list. Problems involving "meeting point."
Core technique: slow moves 1 step at a time, fast moves 2. If they meet β cycle exists. After detecting a cycle, reset one pointer to head to find the cycle start.
Template:
slow, fast = head, head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
# cycle detected
| Question | Difficulty | Link |
|---|---|---|
| LinkedList Cycle | Easy | LeetCode |
| Start of LinkedList Cycle | Medium | LeetCode |
| Happy Number | Medium | LeetCode |
| Find the Duplicate Number | Medium | LeetCode |
| Middle of the LinkedList | Easy | LeetCode |
| Palindrome LinkedList | Medium | LeetCode |
| Reorder List | Medium | LeetCode |
| Circular Array Loop | Hard | LeetCode |
3. Sliding Window¶
When to use: Contiguous subarray or substring problems. Asked for maximum/minimum/longest/shortest within a window. Key signal: "subarray of size k" or "at most k distinct."
Core technique (variable window):
left = 0
for right in range(len(arr)):
# expand window by including arr[right]
while window_is_invalid:
# shrink from left
left += 1
update_answer()
| Question | Difficulty | Link |
|---|---|---|
| Maximum Sum Subarray of Size K | Easy | GFG |
| Smallest Subarray with Given Sum | Easy | LeetCode |
| Longest Substring with K Distinct Characters | Medium | GFG |
| Fruit Into Baskets | Medium | LeetCode |
| Longest Substring Without Repeating Characters | Hard | LeetCode |
| Longest Repeating Character Replacement | Hard | LeetCode |
| Max Consecutive Ones III | Hard | LeetCode |
| Minimum Window Substring | Hard | LeetCode |
| Permutation in String | Hard | LeetCode |
| Find All Anagrams in a String | Hard | LeetCode |
| Substring with Concatenation of All Words | Hard | LeetCode |
4. Kadane's Algorithm¶
When to use: Maximum (or minimum) sum contiguous subarray. Circular subarray variants. Variants that allow one deletion.
Core technique: Track a running sum. If it goes negative, reset it. Update global max at every step.
Template:
max_sum = arr[0]
current = arr[0]
for x in arr[1:]:
current = max(x, current + x)
max_sum = max(max_sum, current)
| Question | Difficulty | Link |
|---|---|---|
| Maximum Subarray Sum | Easy | LeetCode |
| Minimum Subarray Sum | Easy | GFG |
| Maximum Product Subarray | Medium | LeetCode |
| Maximum Subarray Sum with One Deletion | Medium | LeetCode |
| Maximum Absolute Sum of Any Subarray | Medium | LeetCode |
| Maximum Sum Circular Subarray | Medium | LeetCode |
5. Prefix Sum¶
When to use: Range sum queries. Counting subarrays with a target sum. Divisibility of subarrays. "Number of subarrays where sum equals k."
Core technique: Build a running sum array. Use a hashmap to track how many times each prefix sum has been seen.
Template:
prefix = 0
count = 0
seen = {0: 1}
for x in arr:
prefix += x
count += seen.get(prefix - target, 0)
seen[prefix] = seen.get(prefix, 0) + 1
| Question | Difficulty | Link |
|---|---|---|
| Subarray Sum Equals K | Easy | LeetCode |
| Find Pivot Index | Easy | LeetCode |
| Subarray Sums Divisible by K | Medium | LeetCode |
| Contiguous Array (equal 0s and 1s) | Medium | LeetCode |
| Shortest Subarray with Sum at Least K | Hard | LeetCode |
| Count of Range Sum | Hard | LeetCode |
6. Merge Intervals¶
When to use: Problems involving ranges, schedules, or time intervals. "Merge overlapping," "find free time," "minimum rooms needed."
Core technique: Sort by start time. Compare current interval's end with next interval's start.
Template:
intervals.sort(key=lambda x: x[0])
merged = [intervals[0]]
for start, end in intervals[1:]:
if start <= merged[-1][1]:
merged[-1][1] = max(merged[-1][1], end)
else:
merged.append([start, end])
| Question | Difficulty | Link |
|---|---|---|
| Merge Intervals | Medium | LeetCode |
| Insert Interval | Medium | LeetCode |
| Interval List Intersections | Medium | LeetCode |
| Check Overlapping Intervals | Easy | GFG |
| Minimum Meeting Rooms | Hard | GFG |
| Maximum CPU Load | Hard | GFG |
| Employee Free Time | Hard | CoderTrain |
| Non-overlapping Intervals | Medium | LeetCode |
| Meeting Rooms I | Easy | LeetCode |
7. In-place Reversal of a LinkedList¶
When to use: Reverse a portion (or all) of a linked list without extra space. "Reverse every k-group," "rotate list."
Core technique: Keep track of prev, current, and next. Redirect current.next to prev, then advance.
Template:
prev = None
current = head
while current:
next_node = current.next
current.next = prev
prev = current
current = next_node
return prev
| Question | Difficulty | Link |
|---|---|---|
| Reverse a LinkedList | Easy | LeetCode |
| Reverse a Sub-list | Medium | LeetCode |
| Reverse Every K-element Sub-list | Medium | LeetCode |
| Rotate a LinkedList | Medium | LeetCode |
| Reverse Nodes in Even Length Groups | Medium | LeetCode |
8. Heap / Top-K Elements¶
When to use: "Top K," "K closest," "K largest/smallest," "Kth largest," "Median from a data stream." Use a min-heap of size K to track top-K largest elements.
Core technique: - Top K largest β min-heap of size K (pop when size > K) - Top K smallest β max-heap of size K - Median β two heaps: max-heap for lower half, min-heap for upper half
| Question | Difficulty | Link |
|---|---|---|
| Kth Largest Element in an Array | Medium | LeetCode |
| K Closest Points to Origin | Medium | LeetCode |
| Top K Frequent Elements | Medium | LeetCode |
| Sort Characters by Frequency | Medium | LeetCode |
| Kth Largest Element in a Stream | Easy | LeetCode |
| Find Median from Data Stream | Hard | LeetCode |
| Sliding Window Median | Hard | LeetCode |
| Task Scheduler | Medium | LeetCode |
| Reorganize String | Medium | LeetCode |
9. Binary Search¶
When to use: Sorted array. "Find minimum/maximum satisfying a condition." Search space that is monotone (answer is feasible on one side, not the other). Key signal: O(log n) expected complexity.
Template (find leftmost condition):
lo, hi = 0, len(arr) - 1
while lo < hi:
mid = (lo + hi) // 2
if condition(mid):
hi = mid
else:
lo = mid + 1
return lo
| Question | Difficulty | Link |
|---|---|---|
| Binary Search | Easy | LeetCode |
| Search in Rotated Sorted Array | Medium | LeetCode |
| Find Minimum in Rotated Sorted Array | Medium | LeetCode |
| Find Peak Element | Medium | LeetCode |
| Kth Smallest Element in a Sorted Matrix | Medium | LeetCode |
| Search a 2D Matrix | Medium | LeetCode |
| Median of Two Sorted Arrays | Hard | LeetCode |
| Split Array Largest Sum | Hard | LeetCode |
| Capacity to Ship Packages Within D Days | Medium | LeetCode |
| Koko Eating Bananas | Medium | LeetCode |
10. Tree BFS (Level Order)¶
When to use: Level-by-level traversal. "Average of levels," "right side view," "zigzag traversal," "connect level nodes."
Core technique: Use a queue. At each level, process all nodes currently in the queue (that's one level).
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)
| Question | Difficulty | Link |
|---|---|---|
| Binary Tree Level Order Traversal | Medium | LeetCode |
| Binary Tree Zigzag Level Order Traversal | Medium | LeetCode |
| Average of Levels in Binary Tree | Easy | LeetCode |
| Binary Tree Right Side View | Medium | LeetCode |
| Minimum Depth of Binary Tree | Easy | LeetCode |
| Populating Next Right Pointers | Medium | LeetCode |
| Word Ladder | Hard | LeetCode |
11. Tree DFS¶
When to use: Path sum problems. "All root-to-leaf paths," "validate BST," "lowest common ancestor," diameter problems.
Core technique: Recursive pre/in/post-order traversal. Pass state down (e.g. current sum) and accumulate results up.
| Question | Difficulty | Link |
|---|---|---|
| Path Sum | Easy | LeetCode |
| Path Sum II (all paths) | Medium | LeetCode |
| Sum Root to Leaf Numbers | Medium | LeetCode |
| Diameter of Binary Tree | Easy | LeetCode |
| Binary Tree Maximum Path Sum | Hard | LeetCode |
| Lowest Common Ancestor | Medium | LeetCode |
| Validate Binary Search Tree | Medium | LeetCode |
| Construct Binary Tree from Preorder and Inorder | Medium | LeetCode |
| Serialize and Deserialize Binary Tree | Hard | LeetCode |
12. Backtracking¶
When to use: All combinations / permutations / subsets. Constraint satisfaction (N-Queens, Sudoku). "Generate all validβ¦"
Core technique: Make a choice β recurse β undo the choice (backtrack).
Template:
def backtrack(start, path):
if is_solution(path):
results.append(list(path))
return
for choice in choices(start):
path.append(choice)
backtrack(next_start, path)
path.pop() # undo
| Question | Difficulty | Link |
|---|---|---|
| Subsets | Medium | LeetCode |
| Subsets II (with duplicates) | Medium | LeetCode |
| Permutations | Medium | LeetCode |
| Permutations II (with duplicates) | Medium | LeetCode |
| Combination Sum | Medium | LeetCode |
| Combination Sum II | Medium | LeetCode |
| Letter Combinations of a Phone Number | Medium | LeetCode |
| Generate Parentheses | Medium | LeetCode |
| N-Queens | Hard | LeetCode |
| Sudoku Solver | Hard | LeetCode |
| Word Search | Medium | LeetCode |
| Palindrome Partitioning | Medium | LeetCode |
13. Dynamic Programming¶
When to use: "How many ways," "minimum cost," "maximum profit," overlapping subproblems where brute force recurses into the same state multiple times.
Key sub-patterns:
| Sub-pattern | Trigger phrase | Classic problem |
|---|---|---|
| 0/1 Knapsack | "pick items with weight/value constraint" | 0/1 Knapsack |
| Unbounded Knapsack | "unlimited copies of each item" | Coin Change |
| LCS | "longest common subsequence/substring" | LCS |
| LIS | "longest increasing subsequence" | LIS |
| Matrix DP | grid path, island counting | Unique Paths |
| Interval DP | "burst balloons," "matrix chain" | Burst Balloons |
| State Machine DP | buy/sell stock with cooldown/fee | Best Time to Buy and Sell Stock IV |
| Question | Difficulty | Link |
|---|---|---|
| Climbing Stairs | Easy | LeetCode |
| House Robber | Medium | LeetCode |
| House Robber II | Medium | LeetCode |
| Longest Common Subsequence | Medium | LeetCode |
| Longest Increasing Subsequence | Medium | LeetCode |
| Coin Change | Medium | LeetCode |
| 0/1 Knapsack | Medium | GFG |
| Partition Equal Subset Sum | Medium | LeetCode |
| Edit Distance | Medium | LeetCode |
| Unique Paths | Medium | LeetCode |
| Minimum Path Sum | Medium | LeetCode |
| Word Break | Medium | LeetCode |
| Burst Balloons | Hard | LeetCode |
| Best Time to Buy and Sell Stock IV | Hard | LeetCode |
| Regular Expression Matching | Hard | LeetCode |
14. Graph BFS / DFS¶
When to use: Connected components, shortest path in unweighted graph, "number of islands," "rotting oranges," reachability.
Template (BFS):
from collections import deque
visited = set([start])
queue = deque([start])
while queue:
node = queue.popleft()
for neighbor in graph[node]:
if neighbor not in visited:
visited.add(neighbor)
queue.append(neighbor)
| Question | Difficulty | Link |
|---|---|---|
| Number of Islands | Medium | LeetCode |
| Max Area of Island | Medium | LeetCode |
| Clone Graph | Medium | LeetCode |
| Rotting Oranges | Medium | LeetCode |
| Pacific Atlantic Water Flow | Medium | LeetCode |
| Course Schedule (Cycle Detection) | Medium | LeetCode |
| Course Schedule II (Topological Sort) | Medium | LeetCode |
| Word Ladder | Hard | LeetCode |
| Alien Dictionary | Hard | LeetCode |
15. Topological Sort¶
When to use: Ordering tasks with dependencies. "Course prerequisites," "build order," "detect cycle in directed graph."
Core technique (Kahn's BFS): Find all nodes with in-degree 0, process them, reduce neighbors' in-degrees, repeat.
| Question | Difficulty | Link |
|---|---|---|
| Course Schedule | Medium | LeetCode |
| Course Schedule II | Medium | LeetCode |
| Alien Dictionary | Hard | LeetCode |
| Sequence Reconstruction | Medium | LeetCode |
| Minimum Height Trees | Medium | LeetCode |
16. Union-Find (Disjoint Set Union)¶
When to use: Group/connect components dynamically. "Number of connected components," "detect cycle in undirected graph," "accounts merge."
Template:
parent = list(range(n))
rank = [0] * n
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: return False
if rank[px] < rank[py]: px, py = py, px
parent[py] = px
if rank[px] == rank[py]: rank[px] += 1
return True
| Question | Difficulty | Link |
|---|---|---|
| Number of Connected Components | Medium | LeetCode |
| Redundant Connection | Medium | LeetCode |
| Accounts Merge | Medium | LeetCode |
| Most Stones Removed | Medium | LeetCode |
| Number of Operations to Make Network Connected | Medium | LeetCode |
| Satisfiability of Equality Equations | Medium | LeetCode |
17. Monotonic Stack¶
When to use: "Next greater element," "next smaller element," "largest rectangle in histogram," "trapping rain water." The stack maintains a monotonically increasing or decreasing order.
Template (next greater element):
stack = []
result = [-1] * len(arr)
for i, val in enumerate(arr):
while stack and arr[stack[-1]] < val:
result[stack.pop()] = val
stack.append(i)
| Question | Difficulty | Link |
|---|---|---|
| Next Greater Element I | Easy | LeetCode |
| Next Greater Element II (circular) | Medium | LeetCode |
| Daily Temperatures | Medium | LeetCode |
| Largest Rectangle in Histogram | Hard | LeetCode |
| Trapping Rain Water | Hard | LeetCode |
| Maximal Rectangle | Hard | LeetCode |
| Remove K Digits | Medium | LeetCode |
| Sum of Subarray Minimums | Medium | LeetCode |
18. Trie¶
When to use: Prefix search, autocomplete, "word search in a board," "longest common prefix," problems involving a dictionary of words.
Template:
class TrieNode:
def __init__(self):
self.children = {}
self.is_end = False
class Trie:
def __init__(self): self.root = TrieNode()
def insert(self, word):
node = self.root
for ch in word:
node = node.children.setdefault(ch, TrieNode())
node.is_end = True
def search(self, word):
node = self.root
for ch in word:
if ch not in node.children: return False
node = node.children[ch]
return node.is_end
| Question | Difficulty | Link |
|---|---|---|
| Implement Trie | Medium | LeetCode |
| Word Search II | Hard | LeetCode |
| Design Add and Search Words Data Structure | Medium | LeetCode |
| Replace Words | Medium | LeetCode |
| Maximum XOR of Two Numbers in an Array | Medium | LeetCode |
| Longest Word in Dictionary | Medium | LeetCode |
19. HashMap / HashSet¶
When to use: O(1) lookups. Anagram detection, two-sum variants, frequency counting, "first duplicate," "group by."
| Question | Difficulty | Link |
|---|---|---|
| Two Sum | Easy | LeetCode |
| Group Anagrams | Medium | LeetCode |
| Valid Anagram | Easy | LeetCode |
| Top K Frequent Elements | Medium | LeetCode |
| Longest Consecutive Sequence | Medium | LeetCode |
| Intersection of Two Arrays | Easy | LeetCode |
| Contains Duplicate II | Easy | LeetCode |
| Isomorphic Strings | Easy | LeetCode |
20. Bit Manipulation¶
When to use: Problems involving XOR (finding unique elements), counting set bits, checking powers of 2, subsets via bitmask.
Common tricks:
| Trick | Code |
|---|---|
| Check if bit i is set | (n >> i) & 1 |
| Set bit i | n \| (1 << i) |
| Clear bit i | n & ~(1 << i) |
| Toggle bit i | n ^ (1 << i) |
| Remove lowest set bit | n & (n - 1) |
| Isolate lowest set bit | n & (-n) |
| XOR duplicates cancel out | a ^ a == 0 |
| Question | Difficulty | Link |
|---|---|---|
| Single Number | Easy | LeetCode |
| Single Number II | Medium | LeetCode |
| Number of 1 Bits | Easy | LeetCode |
| Counting Bits | Easy | LeetCode |
| Reverse Bits | Easy | LeetCode |
| Power of Two | Easy | LeetCode |
| Sum of Two Integers (no + operator) | Medium | LeetCode |
| Missing Number | Easy | LeetCode |
| XOR Queries of a Subarray | Medium | LeetCode |
Quick Pattern Decision Tree¶
Is the input sorted?
βββ Yes β Two Pointers or Binary Search
β βββ Finding pairs/triplets β Two Pointers
β βββ Finding a value / min-max condition β Binary Search
βββ No β Continue below
Is it a subarray/substring problem?
βββ Fixed size window β Sliding Window (fixed)
βββ Variable size window β Sliding Window (variable) or Prefix Sum
βββ Max/min sum subarray β Kadane's
Is it a tree?
βββ Level-by-level β BFS
βββ Path / depth / ancestor β DFS
Is it a graph?
βββ Shortest path, unweighted β BFS
βββ Shortest path, weighted β Dijkstra
βββ Dependency ordering β Topological Sort
βββ Connectivity / grouping β Union-Find
Is it "how many ways" or "min cost"?
βββ Dynamic Programming
Is it "all combinations / all subsets"?
βββ Backtracking
Does it involve ranges/intervals?
βββ Merge Intervals (sort by start time)
Is it about cycles in a linked list?
βββ Fast & Slow Pointers
Is it about top/bottom K elements?
βββ Heap
Does it involve prefix/word search?
βββ Trie
Last updated: June 2026. All LeetCode links point to the problem description page.