Guide · Career

Track which pattern you fail, not how many problems you did

Interview problems are drawn from a small set of recurring shapes. Solving 400 problems randomly teaches you 400 facts; identifying which of ten patterns you keep failing teaches you the thing that transfers.


Why problem counts are the wrong metric

"I did 300 problems" tells you nothing about readiness, because it does not distinguish between 300 problems in the patterns you already know and 300 spread across the ones you do not. Volume without a diagnosis produces a common and frustrating outcome: a large solved count and a consistent failure on any problem phrased slightly unfamiliarly.

The reframe is simple. An interview problem is a pattern wearing a costume. Your job in the first two minutes is to identify the pattern; the implementation afterwards is mechanical if you have drilled it. So practice should be organised around recognising patterns and around finding the ones where your recognition fails.

The recurring patterns

PatternRecognition cueTypical complexity
Two pointersSorted array, pair or triplet sum, in-place partition, palindromeO(n) after any sort
Sliding windowContiguous subarray or substring, longest or shortest satisfying a conditionO(n)
Binary search on the answerMonotone predicate, "minimum k such that…", "can we do it in x?"O(n log range)
BFS / DFS on graphsGrid, tree, connectivity, shortest path with unit edges, reachabilityO(V + E)
Topological sortDependencies, prerequisites, ordering with constraints, cycle detectionO(V + E)
Heap / top-kK largest, k closest, merge k sorted, running medianO(n log k)
IntervalsMeetings, ranges, merges, overlaps, schedulingO(n log n) with sort
Dynamic programmingCount the ways, optimal value, overlapping subproblems, choices per indexDepends on state space
BacktrackingGenerate all, permutations, combinations, constraint satisfaction, N-queensExponential with pruning
Union-findConnected components, grouping, cycle detection in undirected graphs, KruskalNear O(α(n)) per op

That table is most of the surface area of a standard software interview loop. The remaining problems are usually combinations — a BFS whose frontier is a heap, a DP over intervals, a binary search whose predicate runs a greedy check.

The templates, in one place

Recognition without a template is half a skill. For each pattern there is one canonical shape you should be able to type from memory, at which point the implementation stops consuming the working memory you need for the actual problem. These are sketches, not library code — the value is in the control flow being automatic.

TWO POINTERS i, j = 0, len(a)-1 while i < j: move the pointer that can only improve the objective SLIDING WINDOW lo = 0 for hi in range(n): add a[hi] while invalid: remove a[lo]; lo += 1 best = max(best, hi - lo + 1) BINARY SEARCH ON ANS lo, hi = min_ans, max_ans while lo < hi: mid = (lo + hi) // 2 if feasible(mid): hi = mid else: lo = mid + 1 return lo # feasible() must be monotone BFS q = deque([start]); seen = {start} while q: for each unseen neighbour: mark, push # level order = pop len(q) nodes per round DFS def go(u): seen.add(u) for v in adj[u]: if v not in seen: go(v) TOPOLOGICAL SORT indeg[v] for all v; q = all v with indeg 0 pop u, output u, decrement indeg of neighbours, push any that hit 0 # output shorter than n means a cycle exists HEAP / TOP-K for x in a: push(h, x) if len(h) > k: pop smallest # min-heap of size k gives the k largest INTERVALS sort by start for each iv: if iv.start <= cur.end: cur.end = max(cur.end, iv.end) else: emit cur; cur = iv DP define state in words FIRST, then: dp[i] = f(dp[i-1], dp[i-2], ...) base cases, order of evaluation, answer cell BACKTRACKING def go(path, choices): if complete: record; return for c in choices: if prune(c): continue apply(c); go(path+[c], rest); undo(c) UNION-FIND find(x) with path compression union(a, b) by size or rank # answer is usually a count of distinct roots

Write each of those out from memory once a week until the week where you get all ten right. That is a much shorter project than it sounds, and it removes an entire category of interview failure — the one where you knew exactly what to do and lost eight minutes to an off-by-one in the shrink condition.

The two-minute recognition drill

Recognition is a separate skill from implementation and it is the one that fails under pressure. Drill it separately: read a problem, spend two minutes deciding the pattern and the complexity target, write it down, then check. Do not implement. You can run twenty of these in the time one full solution takes, and it trains exactly the step interviews test first.

For each problem, before coding, answer four questions: 1. What is the input shape? sorted / graph / intervals / string 2. What is being asked? exists / count / optimum / enumerate 3. What complexity is plausible? n log n suggests sort or heap or binary search 4. Which pattern fits? name it, out loud, before typing

Question 3 does more work than people expect. If the constraints allow n up to 10^5, an O(n^2) solution is not the intended one, and that single observation frequently identifies the pattern on its own.

Reading the constraints backwards

The constraint line at the bottom of the problem statement is a hint that most candidates skim. Roughly, a machine does on the order of 10^8 simple operations per second in a compiled language and closer to 10^6 to 10^7 in Python, and interview problems are set so the intended solution fits comfortably inside a second or two. Run the table backwards from n:

Constraint on nComplexity that fitsPatterns it points at
n ≤ 12O(n!) or O(2ⁿ · n)Full permutation search, travelling-salesman style brute force
n ≤ 22O(2ⁿ)Subset enumeration, bitmask DP
n ≤ 200O(n³)Floyd-Warshall, interval or matrix DP
n ≤ 3,000O(n²)Pairwise DP, two-dimensional table, edit-distance shapes
n ≤ 10⁶O(n log n)Sort, heap, binary search, divide and conquer
n ≤ 10⁷O(n)Two pointers, sliding window, counting, single pass
Values up to 10¹⁸, small nO(log V) in the value rangeBinary search on the answer, exponentiation, maths

Two secondary reads matter as much as the primary one. A value range that is enormous while n is small is almost always telling you to search the answer space rather than the input. And a stated memory limit that is tight relative to n² rules out the two-dimensional table you were about to allocate, which usually means a rolling one-dimensional DP.

Three worked recognition drills

The four questions look obvious written down and are surprisingly hard to apply under time pressure. Here they are run end to end on three problem shapes you will meet in some costume or other.

Drill one

Given an array of n positive integers and an integer k, return the length of the longest contiguous subarray whose sum is at most k. 1 ≤ n ≤ 2·10⁵.

  1. Input shape. A flat array, and the word contiguous is doing real work — it rules out anything that reorders or subsets freely.
  2. What is asked. The longest thing satisfying a condition. An optimum over contiguous ranges.
  3. Plausible complexity. n is 2·10⁵, so n² is 4·10¹⁰ and is out. O(n) or O(n log n).
  4. Pattern. Contiguous, plus longest, plus a condition that only worsens as the window grows — sliding window, O(n).

The instructive part is the word positive. Sliding window works here precisely because the sum is monotone in the window size; if the values could be negative, shrinking from the left no longer reliably reduces the sum and the whole approach collapses. Saying that out loud in an interview is worth more than the solution, because it shows you know why the pattern applies rather than that it usually does.

Drill two

You have n tasks with given durations and m identical machines. Each task runs on one machine, machines run tasks sequentially, return the minimum time to finish everything. n, m ≤ 10⁴, durations up to 10⁹.

  1. Input shape. An array of durations plus a count. No graph, no ordering, no adjacency.
  2. What is asked. A minimum value, phrased as "minimum time such that everything finishes".
  3. Plausible complexity. The answer can be as large as 10⁴ · 10⁹ = 10¹³, so you cannot iterate over candidate answers. But log₂(10¹³) is about 44, so you can bisect them.
  4. Pattern. Binary search on the answer, with a greedy feasibility check. Roughly O(n log(max answer)).

The tell is the pair of facts: a minimum T such that phrasing, and a feasibility check that is far cheaper than the search. Confirm monotonicity before you commit — if a schedule finishes within time T, it finishes within T+1, so feasible is monotone and bisection is valid. When that check fails, binary search on the answer is simply wrong, and candidates apply it anyway more often than any other pattern on this list.

Drill three

Given pairs (a, b) meaning course a must be completed before course b, and no limit on how many courses you take per term, return the minimum number of terms needed. n up to 10⁵.

  1. Input shape. Pairs with a direction. That is a directed graph, whatever the problem calls it.
  2. What is asked. A minimum number of rounds, which is a depth rather than a path or a count.
  3. Plausible complexity. 10⁵ nodes means O(V + E). Anything quadratic in V is out.
  4. Pattern. Topological sort, processed in layers — each layer is one term, and the answer is the number of layers, which is the longest chain in the graph.

Two things to say out loud here. First, the answer is the length of the longest dependency chain, which is why layering works. Second, if the problem did cap courses per term, that is a materially harder scheduling problem and not the same exercise — noticing the difference and flagging it is a strong signal, and quietly assuming the greedy answer is correct is a weak one.

Keeping a failure log by pattern

The whole method rests on one artefact: a log where every problem you attempt is tagged with its pattern and an outcome. Not a count — a per-pattern record.

  1. Tag every attempt with one of the ten patterns.
  2. Record the outcome honestly: solved unaided, solved with a hint, or failed.
  3. Record where it broke — recognition, approach, implementation, or edge cases. These are different problems with different fixes.
  4. Review weekly and look for the pattern with the worst ratio. That is your next week.
  5. When a pattern reaches a run of clean unaided solves, stop drilling it and let spaced repetition maintain it.

The failure-location taxonomy

The failure location matters more than the failure, because each location has a different and specific remedy — and the default response of "do more problems in that pattern" is the correct fix for exactly one of them.

Where it brokeWhat it looked likeThe wrong fixThe right fix
RecognitionTen minutes with no candidate pattern at allGrinding problems in patterns you already spotBulk recognition drills: twenty statements, name the pattern only, no code
ApproachNamed the pattern, reduced the problem wronglyReading the editorial and moving onWrite the invariant in one sentence before coding, and redo the problem cold 24 hours later
ImplementationRight approach, buggy code, time goneMore new problemsType the canonical template from memory five times, until the control flow is automatic
Edge casesPasses the samples, fails the hidden testsAdding ad-hoc checks after each failureA standing checklist: empty, single element, all equal, duplicates, negatives, overflow, both ends
ComplexityCorrect solution, too slowMicro-optimising the same algorithmRead the constraints first, every time, and name a target complexity before writing anything
CommunicationSolved it silently, scored badly anywayAssuming the code speaks for itselfNarrate every solve out loud, including the ones you do alone

If you recognise sliding window instantly but keep mishandling the shrink condition, you do not need more sliding-window problems — you need the template rehearsed. If you never recognise it in the first place, the fix is the opposite. Logging the location is what lets you tell those two situations apart, and they are indistinguishable from a solved count.

Spaced repetition, because you will forget

Algorithm knowledge decays like anything else. A problem solved cleanly in March is often a blank in June. Spaced repetition solves this cheaply: re-attempt solved problems on an expanding schedule rather than solving new ones forever.

OutcomeNext reviewRationale
Failed1 dayNothing has been learned yet
Solved with a hint3 daysRecognition is fragile
Solved unaided, slowly1 weekCorrect but not fluent
Solved unaided, fluently3 weeksMaintenance only
Fluent twice in a row2 monthsRetired to background rotation

The practical shape is a Leitner system: five boxes with those review intervals, a problem moves forward on a clean solve and drops back to box one on a failure.

What the schedule actually costs

The arithmetic below is illustrative, but it produces a rule worth having. A problem sitting in box one generates about seven reviews a week; box two about 2.3; box three one; box four about 0.33; box five about 0.12. So the review load is almost entirely determined by how many problems you are holding in box one, and nothing else on the schedule comes close.

reviews/week per problem, by box box 1 (1 day) 7.0 box 2 (3 days) 2.3 box 3 (1 week) 1.0 box 4 (3 weeks) 0.33 box 5 (2 months) 0.12 Holding 8 problems in box 1 = 8 reviews/day at 6 minutes each = 48 minutes/day, before any new work RULE: cap box 1 at about 8 problems. When it is full, you are not allowed a new problem until something graduates. This is a feature - it forces you to fix what is broken instead of collecting more of it.

An eight-week block built on that cap looks like the table below. New problems are deliberately front-loaded and then throttled as the review debt accumulates, which is what actually happens rather than what a plan usually assumes.

WeekTarget patternNew problemsReviews dueBox 1 at week end
1Worst ratio in the log1006
2Same pattern, still worst10~268 (capped)
3Second worst8~347
4Second worst8~385
5Third worst8~405
6Mixed review week, no new pattern4~423
7Whatever regressed in week 68~384
8Timed full loops only3~353

Week six is the one people delete from their plan, and it is the one that makes the other seven work. A week with no new pattern and no new material is where the box-one backlog clears and the earlier weeks convert into something retained rather than something attempted.

Practising out loud, because the interview is verbal

A silent forty-minute solve is a rehearsal for a format that does not exist. In a real loop you are assessed on the reasoning as much as the result, and an interviewer who cannot follow your thinking cannot give you credit for it or steer you when you drift. The specific things to rehearse:

  • Restate the problem in your own words and confirm one edge case before writing anything. It takes forty seconds and catches misread problems.
  • Name the pattern out loud, along with the complexity you are targeting and why the constraints imply it.
  • Say what you rejected. "The brute force is O(n²) which is 4·10¹⁰ here, so it has to be linear" is a complete piece of reasoning in one sentence.
  • Narrate while typing, even badly. Silence longer than about twenty seconds reads as being stuck, which changes what the interviewer does next.
  • Ask before assuming. Duplicates allowed? Sorted? Can it be empty? Fits in memory? Each answer removes a branch.
  • Test out loud at the end with a small case, walking the values rather than staring at the code.

Record one practice solve on your phone and watch it back. It is unpleasant and it is the single highest-yield twenty minutes in this guide — nearly everyone discovers they narrate far less than they believe, and that the long silences land exactly where they are least confident.

A weekly structure that works

  • Start every session with review, not new material. Fifteen to twenty minutes on due problems.
  • One target pattern per week, chosen from the worst ratio in the log, not from a curriculum order.
  • Recognition drills in bulk — a batch of twenty problems where you only name the pattern.
  • Two or three full timed solves, out loud, since interviews are verbal and silence reads as being stuck.
  • Write the template once per pattern — the canonical implementation, from memory, until it is automatic.
  • Stop tracking total solved. It is the metric that feels like progress and measures nothing.
ActivitySessions per weekMinutes eachWeekly total
Review of due problems520100
Recognition drills, no coding22550
Full timed solves, out loud24590
Template rehearsal from memory21530
Log review and next-week planning12020
Total290 min ≈ 4h50m

That is under five hours a week, which is a load a full course schedule can absorb — and over an eight-week block it comes to roughly 39 hours. Compare it with the implicit plan behind "I'll do 300 problems": at a conservative 40 minutes each that is 200 hours, most of it spent re-solving patterns you already own. The pattern method is not merely more effective, it is about five times cheaper, and the cost difference is the entire reason it survives a semester.

The honest test of readiness is not a solved count. It is whether you can be handed an unfamiliar problem in any of the ten patterns and name the pattern within two minutes, then implement its template without looking it up.

The rest of the search — which roles, which deadlines, and the sponsorship questions if you need them — is covered in the internship guide, with the quant and trading variant on a different clock in the quant internship timeline. The pipeline itself lives in Apply OS, the projects you will be asked about are covered in the portfolio guide, and unfamiliar terminology is defined in the glossary.

Tools referenced in this guide

  • Apply OS — application pipeline and deadline radar, free and browser-only.
  • Internship guide — the timeline and sponsorship mechanics around the interviews.
  • Resume rebuild — the document that gets you to the interview in the first place.

FAQ

Quick answers

What are the main coding interview patterns?

Two pointers, sliding window, binary search on the answer, BFS and DFS, topological sort, heap and top-k, intervals, dynamic programming, backtracking, and union-find. Most remaining interview problems are combinations of these, such as a BFS whose frontier is a heap or a binary search whose predicate runs a greedy check.

Why is counting solved problems a bad metric?

Because it does not distinguish between problems in patterns you already know and problems in the ones you do not. A large solved count with no per-pattern diagnosis commonly produces someone who still fails any problem phrased unfamiliarly.

How do you identify which pattern a problem uses?

Answer four questions before writing code: the input shape, what is being asked, the plausible complexity given the constraints, and the pattern name. Complexity does surprising work — if the constraints allow large inputs, an O(n^2) approach is not the intended one, which frequently identifies the pattern by itself.

What do the input constraints tell you about the solution?

They bound the complexity, which usually names the pattern. Roughly, n up to 12 permits factorial search, n up to 22 permits subset enumeration, n up to a few thousand permits quadratic work, and n in the millions demands linear or linearithmic. A huge value range paired with a small n is the standard signal to binary search the answer space rather than the input.

What should a practice log record?

The pattern tag, the outcome, and where the attempt broke — recognition, approach, implementation, or edge cases. Those four failure locations need different fixes: missing recognition needs exposure to more problem statements, while a broken implementation needs the template rehearsed.

How does spaced repetition apply to interview prep?

Re-attempt solved problems on an expanding schedule instead of only solving new ones: one day after a failure, three days after a hinted solve, a week after a slow unaided solve, three weeks after a fluent one. Because a problem in the one-day box generates about seven reviews a week, cap that box at roughly eight problems and refuse new material until something graduates.

How much time per week does pattern-based prep take?

About five hours if you split it into roughly 100 minutes of review, 50 minutes of recognition drills, 90 minutes of timed solves out loud, 30 minutes of template rehearsal, and 20 minutes of log review. Over an eight-week block that is around 39 hours, against roughly 200 hours for a 300-problem grind at 40 minutes each.

How do you know when you are ready?

When you can be handed an unfamiliar problem in any of the ten patterns, name the pattern within about two minutes, and implement its canonical template without looking it up. That is a different test from any solved-problem total, and it should be rehearsed out loud because the interview is verbal.