Why Fifty Questions Are Really Eight Patterns
Candidates who grind hundreds of problems often still freeze in interviews, because they memorised solutions instead of templates. The fifty questions below are the ones that genuinely repeat across screening rounds, and they collapse into eight reusable patterns. Learn the template, and each one unlocks a whole family of questions.
Work through this page with CoderFile's online Python editor open in a second tab. Predict the output, run it, then deliberately break an edge case and run it again. If you want the language-level "gotcha" questions instead of algorithms, read our companion guide on Python interview questions and coding challenges.
Pattern 1 — Hash-Map Counting (Questions 1–8)
Two Sum, group anagrams, first unique character, majority element, contains duplicate, subarray sum equals K, top K frequent elements, and isomorphic strings all reduce to "trade memory for time with a dictionary".
from collections import Counter def two_sum(nums, target): seen = {} for i, n in enumerate(nums): if target - n in seen: return [seen[target - n], i] seen[n] = i return [] def top_k_frequent(nums, k): return [n for n, _ in Counter(nums).most_common(k)] print(two_sum([2, 7, 11, 15], 9))
print(top_k_frequent([1, 1, 1, 2, 2, 3], 2))Complexity: O(n) time, O(n) space. Say that sentence before you write the loop.
Pattern 2 — Two Pointers (Questions 9–15)
Valid palindrome, reverse a string in place, remove duplicates from a sorted array, container with most water, three sum, merge two sorted arrays, and sort colours.
def is_palindrome(s): cleaned = [c.lower() for c in s if c.isalnum()] left, right = 0, len(cleaned) - 1 while left < right: if cleaned[left]!= cleaned[right]: return False left, right = left + 1, right - 1 return True print(is_palindrome("A man, a plan, a canal: Panama"))The tell for this pattern is a sorted input or a symmetric comparison. It turns an O(n squared) nested loop into a single O(n) sweep with O(1) extra space.
Pattern 3 — Sliding Window (Questions 16–21)
Longest substring without repeating characters, maximum sum subarray of size k, minimum window substring, permutation in string, longest repeating character replacement, and maximum consecutive ones.
def longest_unique(s): last, start, best = {}, 0, 0 for i, ch in enumerate(s): if ch in last and last[ch] >= start: start = last[ch] + 1 last[ch] = i best = max(best, i - start + 1) return best print(longest_unique("abcabcbb"))Any question containing "longest", "shortest", or "contiguous" is a window question until proven otherwise. Grow the right edge, shrink the left edge when the window becomes invalid.
Pattern 4 — Stacks and Monotonic Stacks (Questions 22–26)
Valid parentheses, min stack, daily temperatures, next greater element, and evaluate reverse Polish notation.
def valid_parens(s): pairs = {")": "(", "]": "[", "}": "{"} stack = [] for ch in s: if ch in pairs: if not stack or stack.pop()!= pairs[ch]: return False else: stack.append(ch) return not stack def daily_temperatures(temps): out, stack = [0] * len(temps), [] for i, t in enumerate(temps): while stack and temps[stack[-1]] < t: j = stack.pop() out[j] = i - j stack.append(i) return out print(valid_parens("({[]})"))
print(daily_temperatures([73, 74, 75, 71, 69, 72, 76, 73]))Pattern 5 — Binary Search (Questions 27–32)
Classic binary search, search in a rotated sorted array, find first and last position, square root, peak element, and "koko eats bananas" style search-on-answer problems.
def search(nums, target): lo, hi = 0, len(nums) - 1 while lo <= hi: mid = (lo + hi) // 2 if nums[mid] == target: return mid if nums[mid] < target: lo = mid + 1 else: hi = mid - 1 return -1 print(search([1, 3, 5, 7, 9, 11], 7))Watch the two classic bugs: an off-by-one in the loop condition, and integer overflow in other languages (harmless in Python, but mention that you know about it).
Pattern 6 — Tree Traversal (Questions 33–39)
Maximum depth, invert a binary tree, validate a BST, level-order traversal, lowest common ancestor, symmetric tree, and diameter of a binary tree.
from collections import deque class Node: def __init__(self, val, left=None, right=None): self.val, self.left, self.right = val, left, right def level_order(root): if not root: return [] out, q = [], deque([root]) while q: level = [] for _ in range(len(q)): node = q.popleft() level.append(node.val) if node.left: q.append(node.left) if node.right: q.append(node.right) out.append(level) return out tree = Node(1, Node(2, Node(4)), Node(3))
print(level_order(tree))Recursion answers depth questions; a queue answers breadth questions. State which one you are choosing and why before writing code.
Pattern 7 — Graph Traversal (Questions 40–45)
Number of islands, clone a graph, course schedule (cycle detection), word ladder, rotting oranges, and connected components.
from collections import deque def num_islands(grid): if not grid: return 0 rows, cols, count = len(grid), len(grid[0]), 0 for r in range(rows): for c in range(cols): if grid[r][c] == "1": count += 1 q = deque([(r, c)]) grid[r][c] = "0" while q: y, x = q.popleft() for dy, dx in ((1, 0), (-1, 0), (0, 1), (0, -1)): ny, nx = y + dy, x + dx if 0 <= ny < rows and 0 <= nx < cols and grid[ny][nx] == "1": grid[ny][nx] = "0" q.append((ny, nx)) return count print(num_islands([list("11000"), list("11000"), list("00100")]))Use BFS for shortest paths in unweighted graphs and DFS for connectivity or path enumeration. Both are O(V + E).
Pattern 8 — Dynamic Programming (Questions 46–50)
Climbing stairs, house robber, coin change, longest common subsequence, and the 0/1 knapsack.
def coin_change(coins, amount): dp = [0] + [float("inf")] * amount for a in range(1, amount + 1): for c in coins: if c <= a: dp[a] = min(dp[a], dp[a - c] + 1) return -1 if dp[amount] == float("inf") else dp[amount] print(coin_change([1, 5, 6, 9], 11))Every DP answer has the same shape: define the state in one sentence, write the recurrence, choose top-down memoisation or bottom-up tabulation, then state the complexity. If you can say "dp[a] is the fewest coins that make amount a", you have already done the hard part.
A Two-Week Practice Plan
Spend one day per pattern, solving three to five questions from that family and writing the template from memory at the end of the day. Use the second week to mix patterns randomly, because recognising which template applies is the skill that actually gets tested. Rehearse out loud, and time yourself at twenty-five minutes per problem.
When you are ready for a live-format rehearsal, run mock rounds in a shared runnable editor rather than a document — try CoderFile Practice for graded challenges, or the coding interview platform for a real interviewer-and-candidate session with live cursors and execution.