coding interview questions

The 15 coding patterns that cover most interview problems

Most “top 200 interview problems” lists are sorted by which company asked what, which is a backwards way to study. You grind two problems that share an identical solution without ever noticing they share one. The pattern is the unit that transfers. Learn the sliding window properly and you’ve quietly handled forty problems you’ll never have to see in advance.

The fifteen below are what I’d hand someone with six weeks before an onsite: the pattern, the signal in the problem statement that should make you reach for it, and the one problem I’d solve first to make it stick. The table is the index. The reasoning under it is where the choices actually get decided, because half of doing well is spotting the right tool in the first ninety seconds.

Pattern The signal to reach for it Solve this first
Two pointers Sorted array or string, looking for a pair or triplet, or partitioning in place 3Sum, Container With Most Water
Sliding window Longest or shortest contiguous subarray or substring under a constraint Longest Substring Without Repeating Characters, Minimum Window Substring
Fast and slow pointers Linked list cycles, finding the middle, or a value that loops Linked List Cycle, Find the Duplicate Number
Binary search Sorted lookup, or “minimize the maximum / maximize the minimum” Search in Rotated Sorted Array, Koko Eating Bananas
Monotonic stack Next greater or smaller element, spans, rectangles in a histogram Daily Temperatures, Largest Rectangle in Histogram
Heap and top-K The k largest or smallest, a streaming median, merging k sorted things Kth Largest Element, Merge k Sorted Lists
Merge intervals Overlapping ranges, scheduling, room booking Merge Intervals, Meeting Rooms II
Prefix sums Repeated range-sum queries, or subarrays that sum to a target Subarray Sum Equals K, Range Sum Query
Cyclic sort An array holding 1..n and you need the missing or duplicate in O(1) space Missing Number, Find All Duplicates in an Array
Backtracking Enumerate every subset, permutation, or arrangement with pruning Subsets, N-Queens, Word Search
BFS Shortest path on an unweighted graph, or processing level by level Word Ladder, Rotting Oranges
DFS Connected components, does a path exist, anything recursive on a tree Number of Islands, Path Sum
Topological sort Ordering tasks with dependencies, or detecting a cycle in a DAG Course Schedule, Alien Dictionary
Union-Find Dynamic connectivity, counting groups as edges arrive Number of Connected Components, Accounts Merge
Dynamic programming Overlapping subproblems: count the ways, the min cost, the best choice Coin Change, Longest Increasing Subsequence, Edit Distance

The pointer family does more than it looks

Two pointers, the sliding window, and the fast and slow trick are the same idea wearing three coats: walk the data with more than one index so you don’t restart from scratch. The reason it matters is cost. A naive subarray check is O(n²) because you recompute the window every time you slide it. Keep a running state instead and you drop to O(n).

The window version is the one people fumble, usually because they try to track too much. The template is small. Expand the right edge, and when the window breaks the rule, shrink the left edge until it’s valid again.

def longest_unique(s):
    seen = {}
    left = best = 0
    for right, c in enumerate(s):
        if c in seen and seen[c] >= left:
            left = seen[c] + 1
        seen[c] = right
        best = max(best, right - left + 1)
    return best

Reach for two pointers the moment the input is sorted and you want a pair. The sorting is the giveaway. If a problem hands you a sorted array and asks for two values that sum to a target, anything fancier than two converging pointers is overthinking it.

Binary search is wider than sorted arrays

Everyone knows binary search on a sorted list. The version that separates people is binary search on the answer. When a problem asks you to minimize the maximum of something, or maximize the minimum, and you can cheaply check “is X achievable?”, you can bisect the possible answers even though there’s no sorted array in sight.

Koko Eating Bananas is the cleanest example. You’re picking an eating speed, and a faster speed is always at least as feasible as a slower one, so the feasible speeds form a sorted boolean line you can bisect.

def min_eat_speed(piles, h):
    lo, hi = 1, max(piles)
    while lo < hi:
        mid = (lo + hi) // 2
        hours = sum((p + mid - 1) // mid for p in piles)
        if hours <= h:
            hi = mid
        else:
            lo = mid + 1
    return lo

If you see “smallest value such that…” or “largest capacity that still fits”, check whether feasibility is monotonic. When it is, you’ve turned an optimization into a search and shaved a factor off the runtime.

Monotonic stack and heaps maintain order as you go

A monotonic stack keeps its elements in increasing or decreasing order, popping anything that violates the order before it pushes. That single rule answers a whole class of “next greater element” questions in O(n), and it’s the trick behind Largest Rectangle in Histogram, which is otherwise a mess of nested loops. The tell is any problem about the next bigger or smaller thing to your left or right.

Heaps show up whenever you care about the extreme but not the full sort. You don’t need to sort a million numbers to find the ten largest; a heap of size ten does it in O(n log k). Merging k sorted lists, finding a running median with two heaps, pulling the next-soonest task off a schedule all live here. If the words “k largest”, “k closest”, or “median of a stream” appear, you’re reaching for a heap.

Three ways to stop scanning arrays the slow way

Prefix sums turn repeated range queries into constant-time lookups. Precompute a running total, and the sum of any range is one subtraction. Paired with a hash map, the same idea counts subarrays that hit a target sum, which is the actual move in Subarray Sum Equals K.

Cyclic sort is the niche one worth knowing because it reads like a trick in the room. When an array contains the numbers 1 through n in some order, you can place each value at its matching index in a single pass, and whatever’s left out of place reveals the missing or duplicated number using no extra space. Interviewers like it precisely because the brute force with a hash set is so obvious.

Intervals are their own small world: sort by start time, then sweep left to right and merge anything that overlaps. Once you’ve internalized that sort-then-sweep move, Merge Intervals, Insert Interval, and Meeting Rooms collapse into the same handful of lines with different bookkeeping.

Graphs split into four patterns

Most grid and graph problems are a traversal in disguise, and the choice between BFS and DFS is rarely arbitrary. BFS explores in rings, so it gives you the shortest path on an unweighted graph for free; that’s why Word Ladder and Rotting Oranges want a queue, not recursion. DFS goes deep, which suits counting connected components or asking whether any path satisfies a property. Number of Islands works either way, but the moment “shortest” or “fewest steps” enters the prompt, BFS is the answer.

Topological sort is BFS or DFS with a dependency twist: order the nodes so every edge points forward, and if you can’t, there’s a cycle. Course Schedule is the canonical version, and it’s really just asking whether a dependency graph has a cycle. Union-Find is the other graph tool, built for connectivity that changes as edges arrive. When you’re counting groups, detecting that two things just joined the same component, or merging accounts that share an email, a disjoint-set structure with path compression beats re-running a traversal every time.

Backtracking and DP are where candidates lose time

Backtracking is brute force with a brain: try a choice, recurse, undo it, try the next. The skill isn’t the recursion, it’s the pruning. N-Queens is tractable only because you abandon a branch the instant two queens threaten each other instead of generating every board. If a problem asks for all subsets, all permutations, or every valid arrangement, you’re backtracking, and your runtime depends entirely on how early you can cut dead branches.

Dynamic programming is the one people fear, and most of that fear is bad framing. DP is recursion where the subproblems repeat, so you cache them. Write the brute-force recursion first, notice you’re solving the same call twice, add a memo, and you’ve got top-down DP. Coin Change, Longest Increasing Subsequence, and Edit Distance all start as plain recursions that happen to overlap. The hard part is naming the state, the few variables that fully describe a subproblem, and that’s worth practicing on paper before you touch a keyboard.

What the index is for

The point of carrying this list isn’t to label problems after you solve them. It’s the first ninety seconds, when you read the prompt and ask which signal is present. Sorted input and a pair? Two pointers. Contiguous and “longest”? Window. Dependencies? Topological sort. Most interview problems announce their pattern in the constraints if you’ve trained yourself to listen for it. A few don’t, and those are usually two patterns stacked, like a binary search whose feasibility check is itself a greedy sweep. When nothing fits, write the brute force out loud and look at what’s redundant; the pattern is almost always hiding in the part you’re repeating. Bit manipulation and tries earn a spot once you’re past these fifteen, but clear this set first and you’ll recognize the bones of most problems before you’ve finished reading them.

newsletter

What's actually being asked right now

Interview patterns & comp trends, straight to your inbox.

No spam. Unsubscribe anytime.

newsletter

What's actually being asked right now

Interview patterns & comp trends, straight to your inbox.

No spam. Unsubscribe anytime.

1972 Soviet postage stamp commemorating the Mars 2 probe

worth a read

Mars For The Rest of Us — a weekly-or-more deep dive on the technical side of Mars exploration: rocket propulsion, microbiology, mission architecture, and everything in between. Written by Maciej Ceglowski.

Read it on Substack →
Scroll to Top