Cracking the Coding Interview: A Working Method
A repeatable method for the 45-minute coding interview: how to budget the clock, pick the pattern from the constraints, narrate while you type, and defend your complexity.

Most people prepare for coding interviews by solving more problems. That works up to a point and then stops, because after the first hundred problems the bottleneck is no longer whether you have seen the trick. It is whether you can run a reliable process on a problem you have not seen, while a stranger watches, in about forty-five minutes.
This is that process. It is boring on purpose. Boring is what survives adrenaline.
Budget the clock before you touch the keyboard#
A standard remote loop gives you 45 minutes with roughly 40 of them usable. Spend them like this:
| Phase | Minutes | What "done" looks like |
|---|---|---|
| Clarify | 2–4 | You can state the input types, the bound on n, and the return value |
| Choose an approach | 3–6 | You have named a brute force and a target complexity out loud |
| Code | 15–20 | A complete function, not a sketch |
| Test | 5–8 | One normal case and two edge cases, traced by hand |
| Follow-ups | 5 | Complexity, alternatives, what changes at scale |
The single most common failure is spending twenty-five minutes coding and zero minutes testing, then finding a bug at minute forty with no time to fix it. Testing is not the part you cut when you are behind. It is the part that catches the bug that would otherwise end the interview.
Clarify: five questions, always the same five#
Ask these before the approach, every time, in this order:
- What are the input types and ranges? "Are these 32-bit integers? Can they be negative?"
- How big is n? This is the most valuable question in the interview and most candidates skip it. See the next section.
- Is the input sorted, or can I sort it? Sorting costs O(n log n) and buys two pointers and binary search.
- What are the degenerate inputs? Empty array, single element, all elements equal, no valid answer.
- What exactly do I return? The value or the index? All answers or any answer? What on failure?
Write the answers as a comment block at the top of the file. That block is your contract, and when you get lost at minute thirty it is the thing you re-read.
Let the constraints name the pattern#
The bound on n is not trivia. It tells you the complexity class the interviewer expects, and the complexity class narrows the pattern to two or three candidates. Memorize this mapping:
| Bound on n | Complexity you can afford | Patterns that live there |
|---|---|---|
| n ≤ 12 | O(n!) or O(2ⁿ · n) | Permutations, brute-force backtracking |
| n ≤ 25 | O(2ⁿ) | Subset enumeration, meet in the middle |
| n ≤ 500 | O(n³) | Interval DP, Floyd–Warshall |
| n ≤ 5,000 | O(n²) | Pairwise DP, two nested loops |
| n ≤ 10⁶ | O(n log n) | Sort, heap, binary search on the answer |
| n ≤ 10⁷ | O(n) | Hash map, prefix sums, sliding window, single pass |
So "the array has up to a million elements" is the interviewer telling you that the nested loop is wrong and that you should be looking for a single pass with a hash map, a sliding window, or a sort. Saying that out loud — "a million elements rules out O(n²), so I am looking for something linear or n log n" — is worth more than the first ten lines of code you would otherwise have written.
Say the brute force out loud, then improve it#
Never open with the clever solution, even when you know it. Open with the obvious one:
"The brute force is a double loop: for every start index, extend until I hit a repeat. That is O(n²) time and O(n) space for the seen-set. Given n up to 10⁵ I want linear, so let me look for what the double loop recomputes."
That sentence does four things at once. It proves you understood the problem, it establishes a baseline you can fall back to, it states the target, and — this is the important part — it names the reason the optimization exists. Almost every linear-time trick in interview algorithms is an answer to "the brute force recomputes something it already knew." Prefix sums answer it for range totals. Sliding windows answer it for contiguous subarrays. Hash maps answer it for lookups. Monotonic stacks answer it for "next greater element."
If you can articulate what is being recomputed, the pattern usually falls out. If you cannot, you still have a correct brute force and a candidate who is reasoning, which is a far better position than a blank screen.
Worked example: the narration, not just the code#
Problem: given a string, return the length of the longest substring with no repeated characters. n up to 5 · 10⁴.
Here is the whole interview, condensed to what you say and when.
Clarify: "Are these ASCII or full Unicode? Can the string be empty? I return a length, not the substring itself?"
Brute force: "For each start, extend while characters are unseen. O(n²). n is 50,000, so that is 2.5 billion operations — too slow. What does it recompute? When the window starting at index 0 fails at index 7, I throw away everything I learned and start again at index 1. But I already know the substring from 1 to 6 is valid. That is the waste."
Approach: "So I keep a window and only ever move both ends forward. I track the last index I saw each character at. When I meet a repeat, I jump the left edge to just past that previous occurrence instead of walking it. Both pointers move forward at most n times, so it is O(n) time and O(k) space for the alphabet."
Code:
def length_of_longest_substring(s: str) -> int:
last_seen: dict[str, int] = {}
best = 0
left = 0
for right, char in enumerate(s):
# Only jump left forward. `max` matters: a repeat from BEFORE the
# current window is already excluded, and moving left backwards
# would silently re-admit a duplicate.
if char in last_seen and last_seen[char] >= left:
left = last_seen[char] + 1
last_seen[char] = right
best = max(best, right - left + 1)
return bestTest, out loud, by hand:
"abcabcbb"→ window grows toabc, hitsaat index 3, left jumps to 1, best stays 3. Returns 3.""→ the loop never runs, returns 0."bbbb"→ every character repeats immediately, left tracks right, best is 1."abba"→ this is the case the>= leftguard exists for. At index 3 we seea, whose last index is 0, but left is already 2. Without the guard, left would move backwards to 1 and we would return 3 instead of 2.
That last bullet is the highest-value sentence in the whole interview. You did not just test — you tested the specific case your implementation could plausibly get wrong, and you explained the invariant that protects it. Interviewers write that down.
Complexity: "O(n) time — each pointer advances at most n times. O(min(n, k)) space, where k is the alphabet size, because the map holds at most one entry per distinct character."
Narrate in the interviewer's language#
Thinking aloud is not chatter. It is three specific kinds of statement:
- Decisions with reasons. "I am using a hash map rather than sorting because I need the original indices."
- Invariants. "Everything left of
leftis excluded; everything between the pointers is unique." - Uncertainty, named. "I think this handles duplicates but I want to trace
abbabefore I claim it."
The third is the one candidates avoid because it feels like weakness. It reads as the opposite. An engineer who flags the risky case before it bites is an engineer you can ship with.
Defend the complexity, do not recite it#
"O(n log n)" is an answer. "O(n log n), dominated by the sort; the scan after it is linear, and I cannot beat n log n here without assuming bounded integers, in which case counting sort makes it linear" is a hire signal. Complexity questions are follow-up bait: the interviewer is checking whether the bound is something you derived or something you remembered.
Two things to have ready for every solution: which line dominates, and what would have to change about the input for a better bound to be possible.
System design, briefly and concretely#
For mid-level and above, expect one open-ended design round. The trap is starting with boxes and arrows. Start with numbers instead: daily active users, requests per second at peak, average payload size, read-to-write ratio, retention. Ten seconds of arithmetic ("a million writes a day is about twelve per second average, call it sixty at peak") turns an unbounded conversation into an engineering problem with a scale, and the scale tells you whether you need sharding at all.
Then work outside in: API surface, data model, storage choice, the read path, the write path, and only then caching, replication, and failure. Say the trade-off every time you make a choice — "a queue here buys me durability under a write spike and costs me read-after-write consistency" — because the trade-off is the thing being graded, not the box.
Behavioral rounds are scored, not chatted#
Prepare four stories: a conflict, a failure, a project you led, and a technically hard decision. Put each in STAR form and time it — two minutes each, not six. The most common failure is a story with a great Situation and no Result. Land every one on a specific outcome: latency numbers, an incident that stopped recurring, a person whose work changed.
Where AI belongs in preparation#
AI assistants have changed practice more than they have changed the interview. Three uses that genuinely help:
- Explain your own solution back. Paste your working code and ask for the edge case it misses. It is a faster reviewer than a friend and available at midnight.
- Generate the hard test cases. Ask for adversarial inputs for a specific function, then trace them by hand. Tracing is the skill; generation is not.
- Drill the narration. Have it act as the interviewer and interrupt you. The gap between knowing a solution and being able to explain it under interruption is exactly what the interview measures.
The trap is passive reading. Watching a correct solution appear produces recognition, not recall, and recognition collapses the moment the problem is slightly different. If a tool wrote it, close it and write it again from an empty file before you count it as learned.
For the live interview itself, Stealth Interview is a desktop app for macOS and Windows built for the moment the problem is actually on screen: it reads the coding problem from a screenshot, returns a working solution with a step-by-step explanation and its time and space complexity, transcribes the interviewer's audio in real time so nothing gets missed, and stays invisible to screen sharing. It runs on multiple AI models and is driven entirely by keyboard shortcuts, so nothing on screen changes while you use it.
The practice loop that actually compounds#
Solve the problem. Then, before you look at any solution, write down what you tried and where you stalled. Then look. Then — and this is the step everyone skips — close everything and reimplement it from scratch the next day. Recall, not recognition.
Keep one file with a section per pattern. Under each: the signal that identifies it, a template, and the bug you personally make. Yours will be specific, and that is the point — off-by-one on the sliding window's right edge, forgetting to mark visited on push rather than pop, mishandling the mid calculation on binary search. That file, read the morning of the interview, is worth more than another twenty problems.
Interview skill is a skill. It responds to deliberate practice like any other, and it is far more learnable than the people who are already good at it tend to admit.
Frequently asked questions
- How many LeetCode problems do I need to solve before an interview?
- Coverage matters more than count. Roughly 100 problems chosen to cover every major pattern — two pointers, sliding window, hash map, binary search on the answer, BFS/DFS, topological sort, heap, intervals, backtracking, and the four common DP shapes — beats 400 problems clustered in whatever the daily challenge happened to be. The signal you are ready is that you can name the pattern from the constraints before you write a line.
- What should I do when I get completely stuck in a coding interview?
- Say what you have and what you need out loud, then reduce the problem. Solve it for n = 1, solve it brute force, or solve a version with one constraint removed. A candidate who says 'the O(n squared) version is a double loop; I am looking for a way to avoid rescanning the prefix' has given the interviewer something to hint against. Silence gives them nothing to work with.
- Do interviewers care more about the optimal solution or the explanation?
- They score both, but the explanation is what separates candidates who reached the same answer. A working brute force that you analyzed, tested, and then improved reads as engineering. An optimal solution you produced without being able to say why it is correct reads as recall, and the follow-up question will expose it.
- How long should I spend clarifying the problem before coding?
- Two to four minutes of a 45-minute interview. Long enough to pin the input types, the size of n, whether the input is sorted, what happens on empty or duplicate input, and what the function returns. Short enough that you are typing by minute five.
Keep reading

Blind 75: What the List Is and How to Finish It in Six Weeks
The Blind 75 is a seventy-five-problem list that has become the default answer to "what should I actually solve before an interview". It is named after Blind,…

The Coding Interview Cheat Sheet: Complexity, Patterns and Python Idioms
This coding interview cheat sheet is the reference sheet I would want open during preparation: the complexity budget implied by each input size, what every…

Amazon Online Assessment: Format, What It Tests, and How to Prepare
The Amazon online assessment is the automated screen that stands between an application and a human interviewer for most software engineering roles, including…