The coding round, step by step
New to Big O or sorting? Open a quick recap. Each takes about two minutes.
Quick recapBig O· 2 min
Big O says how the work grows with the input size n. O(n) means one pass: twice the input, twice the work. O(n²) means a pass for every item: twice the input, four times the work. At 100,000 items, that’s the difference between a blink and minutes.
Quick recapSorting· 2 min
Python’s sorted() returns a new sorted list and leaves the original alone; list.sort() sorts in place. Both
take O(n log n). A list of lists is sorted by the first item, then the second: [[9, 11], [9, 10]] sorts to
[[9, 10], [9, 11]].
See the problem
Section titled “See the problem”You studied for weeks. In the interview you get a question you’ve seen before. You type the solution in 10 minutes, the interviewer asks a few questions, and you leave feeling great. A week later: no offer.
What happened? You solved a slightly different problem than the one asked. The interviewer heard nothing for 10 minutes, so they couldn’t tell how you think. And you never tested your code, so you didn’t see the bug they spotted in a second.
Interviewers don’t only score the answer. They score how you get there: how you communicate, solve problems, write code, test and analyze. A method gives all five a place, even when you’re nervous.
Define the task
Section titled “Define the task”The method, in seven steps:
- Clarify. Ask about the input, the output and the edge cases. Restate the problem in your words.
- Examples. Work a small example by hand, plus one tricky one.
- Brute force. Say the simplest correct idea and its cost. Don’t code it yet.
- Optimize. Find the slow part and improve it. Agree on the plan with the interviewer.
- Code. Write clean code and talk as you go.
- Test. Walk through your code with an example, then try the edge cases.
- Analyze. State the time and space, and what you’d change for bigger inputs.
The question for this lesson, as an interviewer would say it:
“Our office has meeting rooms. Given a list of bookings, merge the ones that overlap.”
That’s all you get. It sounds clear. It isn’t.
Pause and think
Section titled “Pause and think”Hint 1 of 3
What does one booking look like? Are the bookings in any order?
Hint 2 of 3
Bookings from 13 to 15 and from 15 to 16: do they overlap? Who decides?
Hint 3 of 3
What should happen with no bookings? With 100,000?
Understand the idea
Section titled “Understand the idea”Here is how a strong candidate spends a 45-minute round on this question, minute by minute. The first 5 minutes are introductions, and the last 7 are follow-ups and the candidate’s own questions.
-
Minutes 5–9, clarify. “Is a booking a start and an end, like 9 and 10? Are they sorted? If one ends at 15 and the next starts at 15, do they merge? Can the list be empty? How many bookings? May I change the list I’m given?”
The interviewer’s answers: bookings are
[start, end]pairs of whole hours, with start before end. They come in any order. Touching bookings merge, because the room is busy without a break. The list can be empty and can hold 100,000 bookings. Return the blocks sorted by start, and don’t change the list you’re given. -
Minutes 9–12, examples. “So 9–10, 13–15, 9–11 and 15–16 become 9–11 and 13–16, because you said touching ones merge. And an empty list gives an empty list.”
-
Minutes 12–14, brute force. “Simplest idea: for each booking, find every block it overlaps and merge them into one. That’s a scan of all blocks per booking: O(n²). Fine for a room, slow for 100,000 bookings.”
-
Minutes 14–18, optimize. “The slow part is searching all blocks. If the bookings were sorted by start, only the last block could overlap the next booking. Sorting costs O(n log n), then one pass. Shall I code that?”
-
Minutes 18–30, code. Writes the Strong code below, saying what each line is for: “I sort a copy so I don’t change your list…
<=because touching bookings merge…” -
Minutes 30–36, test. Walks through the example line by line, then tries: empty, one booking, no overlaps, all touching, one booking inside another.
-
Minutes 36–38, analyze. “O(n log n) time for the sort, O(n) for the pass. O(n) extra space for the sorted copy and the result.”
Climb the ladder
Section titled “Climb the ladder”Three candidates, same question, same 45 minutes. Each one shows what they did, their code and what the interviewer writes down.
Codes at once, in silence
The idea: “I’ve seen this one.” Types for 8 minutes without a word, runs it on one sorted example, and says it’s done.
- ✗ No questions. It treats 13–15 and 15–16 as separate and assumes the list is sorted. Both are wrong here.
- ✗ Silence. For 8 minutes the interviewer has nothing to score but typing.
- ✗ No testing. It crashes on an empty list, and on the interviewer’s own example it gives 9–10, 13–15, 15–16: the 9–11 booking disappears.
- ✗ Can change the caller’s data.
mergedstarts with the first booking itself, not a copy, somerged[-1][1] = …can edit the first booking passed in.
"""The weak candidate's code: typed at once, in silence, from memoryof a similar problem. It works on the example they tried, and littleelse."""
def merge(bookings): merged = [bookings[0]] # crashes on an empty list for start, end in bookings[1:]: # assumes the bookings come sorted if start < merged[-1][1]: # treats touching bookings as separate merged[-1][1] = max(merged[-1][1], end) # can edit the caller's first booking else: merged.append([start, end]) return merged- Runs in
O(n), but wrong- Likely verdict
no- Why
- Fast and confident, on a problem the interviewer didn't ask: it assumes sorted input and that touching bookings stay apart.
What the interviewer writes: “Didn’t clarify. Couldn’t explain the approach. Didn’t test; missed basic cases.”
A correct brute force, explained
The idea: Asks two questions, talks through a brute force and codes it. Tests the example. Says “O(n), I think” when asked.
- ✓ Asked about order and touching bookings, so the answer is right.
- ✓ Talked while coding. The interviewer could follow.
- ✗ Stopped at the brute force. With 100,000 bookings, scanning every block for every booking is far too slow.
- ✗ Tested only the example, and guessed the complexity instead of working it out: it’s O(n²), not O(n).
"""The decent candidate's code: a correct brute force. Each bookingswallows every block it overlaps or touches. Right answers, but eachbooking scans all the blocks so far: O(n^2)."""
def merge(bookings): blocks = [] for start, end in bookings: hits = [b for b in blocks if b[0] <= end and start <= b[1]] for b in hits: blocks.remove(b) start = min([start] + [b[0] for b in hits]) end = max([end] + [b[1] for b in hits]) blocks.append([start, end]) return sorted(blocks)- Runs in
O(n²)- Likely verdict
borderline- Why
- It's correct on every input and the reasoning was out loud. But it never looked for a faster way, and the complexity answer was wrong.
What’s missing: the step from brute force to better: find the slow part (searching every block) and remove it. Then test on purpose, and work out the cost line by line.
All seven steps, out loud
The idea: Clarifies, works examples, and states the brute force and its cost. Finds the sorted-order idea and agrees on the plan. Codes it while talking, tests on purpose and states the cost.
- Clarify. Six short questions, in about four minutes. The answers change the code: sort first, and merge on
<=. - Examples. The interviewer’s example, plus one where a booking sits inside another (1–10 and 2–3).
- Brute force. Said out loud with its cost, O(n²). A safe fallback if time runs out.
- Optimize. “After sorting, only the last block can overlap.” Asked “Shall I code that?” before starting.
- Code. Sorted a copy, so the caller’s list is untouched. Short names, one idea per line.
- Test. Walked through the example, then 5 edge cases from a list made in step 1. Found and fixed one bug:
max()for a booking inside another. - Analyze. O(n log n) time for the sort plus O(n) for the pass; O(n) extra space.
"""The strong candidate's code: sort by start, then one pass.A booking that starts before the last block ends, or exactly whenit ends, joins that block. O(n log n) for the sort, O(n) for thepass. The caller's list is not changed."""
def merge(bookings: list[list[int]]) -> list[list[int]]: blocks: list[list[int]] = [] for start, end in sorted(bookings): if blocks and start <= blocks[-1][1]: # overlaps or touches it blocks[-1][1] = max(blocks[-1][1], end) else: blocks.append([start, end]) return blocks- Runs in
O(n log n)- Likely verdict
yes- Why
- Every step gives the interviewer something to score, and the optimization came from naming the slow part of the brute force, not from memory.
It’s not about speed. The strong candidate wrote the first line of code at minute 18, about ten minutes after the weak one. They still ended with working, tested code, because they never had to start over.
Write it yourself
Section titled “Write it yourself”Now you code the strong solution. Merge bookings that overlap or touch, return the blocks sorted by start, and don’t change the input list. Hidden tests check that your input is left as it was. A speed test has 40,000 bookings, so the O(n²) brute force fails it.
Merge overlapping bookings
Ctrl + Enter runs- Not run yet:
merge([[9, 10], [13, 15], [9, 11], [15, 16]])→[[9, 11], [13, 16]] - Not run yet:
One booking inside another→[[1, 5]] - Not run yet: Extra test
- Not run yet: Extra test
- Not run yet: Extra test
- Not run yet: Extra test
- Not run yet: Extra test
- Not run yet: Extra test
Extra tests check tricky cases. You see their input only if they fail.
Try your own input
Compare
Section titled “Compare”| What interviewers score | Weak | Decent | Strong |
|---|---|---|---|
| Communication | Silent while coding | Explains as they go | Explains, checks in, agrees the plan first |
| Problem solving | Jumps to a remembered answer | Correct brute force, stops there | Brute force, then names the slow part and fixes it |
| Code | Short, but wrong and changes input | Correct, a bit clumsy | Correct, clear, leaves the input alone |
| Testing | None | The given example only | A walk-through, then chosen edge cases |
| Analysis | None | A guess, and wrong | Time and space, worked out from the code |
Common mistakes and edge cases
Section titled “Common mistakes and edge cases”- Too many questions is a smell too. Ask the ones that change the code: order, ties and boundaries, empty input, size, and whether you may change the input. Then go.
- Silence is the most common mistake. If you need to think, say so: “Let me think about how to avoid scanning every block for 30 seconds.” Then share what you found.
- Stuck? Say what you know and what fails. Try a smaller example by hand, or ask a specific question: “Would it help if the bookings were sorted?” A good hint taken well is not a fail.
- Test the code you wrote, not the code you meant. Read it line by line with real numbers. Most bugs hide in the boundaries:
<or<=, the first item, the last item. - Use the language you know best. Python is fine nearly everywhere, and its
sorted(),dictandcollectionsare allowed unless the interviewer says otherwise. - Running out of time? Say what’s left, finish the core idea, and leave a clear stub for helpers. A working main path beats a half-typed perfect one.
Say it in the interview
Section titled “Say it in the interview”Questions to ask first (on almost any question)
- What does the input look like, and is it sorted?
- Can it be empty? Can there be duplicates or ties?
- How big can it get?
- What should I return, and in what order? What if there’s no answer?
- May I change the input?
A 60-second opening, after the question
“Let me check I’ve got it. I get a list of bookings, each a start and an end, in any order. I return the busy blocks sorted by start, with touching bookings merged, without changing the list. For example, 9–10, 13–15, 9–11 and 15–16 become 9–11 and 13–16. The simplest way is to merge each booking into every block it overlaps, which is O(n²). The slow part is searching all the blocks. If I sort by start first, only the last block can overlap the next booking. So it’s one pass after an O(n log n) sort. Shall I code that?”
Likely follow-ups
- What if bookings arrive one at a time, all day? Keep the blocks in a sorted structure and insert each new booking with a binary search, merging with its neighbours.
- What if there are too many to fit in memory? Sort them on disk in chunks, then merge the sorted chunks in one pass: the same idea, at a bigger scale.
- How many rooms do we need? A different question: count how many bookings overlap at the busiest moment. Sort starts and ends, or use a heap.
- Can you do it in O(1) extra space? Sort the list in place and write the result into it, but only if the caller agrees that you may change their list.
Red flags interviewers notice
- Coding before asking a single question.
- Long silences, or talking without saying anything useful.
- Saying “It works” without trying it.
- Guessing the complexity, or not knowing what
sorted()costs. - Arguing with a hint instead of trying it.
Practice
Section titled “Practice”Four drills, from easy to hard. Each has a hint or two, then weak, decent and strong answers. Do each one out loud, with a timer, before you open the answers.
1. Clarifying questions (easy)
Section titled “1. Clarifying questions (easy)”The interviewer says: “Return the k most frequent words in a text.” You have two minutes. What do you ask?
Hint 1 of 2
What counts as a word? Is “The” the same as “the”?
Hint 2 of 2
Two words appear the same number of times. Which comes first?
Show the answers
No questions
The idea: Starts coding a Counter at once.
- Questions
none- Risk
solves a different problem- Why
- Case, punctuation and ties all change the output. The code may be right for a question nobody asked.
Asks about the input only
The idea: “How big is the text? Is it all lowercase?”
- Questions
two- Risk
ties and k left open- Why
- Good start, but the output is still unclear: what happens on a tie, or when k is bigger than the number of words?
The questions that change the code
The idea: “Is ‘The’ the same as ‘the’? Does punctuation count? On a tie, alphabetical? What if k is bigger than the number of different words? How big is the text: does it fit in memory?”
- Questions
five, in under two minutes- Risk
small- Why
- Each answer changes a line: lowercasing, the split, the sort key, a bound on k, and Counter versus a streaming count.
2. Brute force to better (easy)
Section titled “2. Brute force to better (easy)”“Given a list of numbers, does any value appear twice?” Say the brute force and its cost, then improve it, out loud.
Hint 1 of 2
Compare every pair. How many pairs are there?
Hint 2 of 2
What do you need to remember about the numbers you’ve already seen?
Show the answers
Jumps to a one-liner
The idea: “return len(set(nums)) != len(nums)”, with no reasoning.
return len(set(nums)) != len(nums)- Runs in
O(n)- What's heard
a memorized trick- Why
- Correct, but the interviewer learns nothing about how you'd solve a problem you haven't seen.
Brute force, then sorting
The idea: “Compare every pair: O(n²). Better: sort, then duplicates sit next to each other, so O(n log n).”
nums = sorted(nums)return any(a == b for a, b in zip(nums, nums[1:]))- Runs in
O(n log n)was O(n²)- What's heard
clear steps- Why
- A real improvement, explained. One step short of the best.
Name what to remember
The idea: “The brute force rechecks old numbers. If I remember what I've seen in a set, each check is O(1), so one pass is O(n), with O(n) space. If memory is tight, sorting in place is the trade-off.”
seen = set()for x in nums: if x in seen: return True seen.add(x)return False- Runs in
O(n)was O(n log n)- What's heard
the slow part, named and removed- Why
- It stops at the first duplicate, and the trade-off between time and memory is said out loud.
3. Test your own code (medium)
Section titled “3. Test your own code (medium)”A candidate wrote this to find the longest run of the same character, like 3 for "aabbbc". It returns 3 for that example. Test it out loud and find the bug.
def longest_run(s): best = run = 1 for i in range(1, len(s)): if s[i] == s[i - 1]: run += 1 else: best = max(best, run) run = 1 return bestHint 1 of 2
Where can the longest run be? Try one at the very end.
Hint 2 of 2
What about an empty string?
Show the answers
“It works on the example”
The idea: Runs “aabbbc”, gets 3, and stops.
- Bugs found
none- Cases tried
one- Why
- The example's longest run isn't at the end of the string, so the bug never shows.
Tries random extra inputs
The idea: Tries “abc” and “abbb”, finds “abbb” gives 1 instead of 3, and patches it.
- Bugs found
one, by luck- Cases tried
three- Why
- Found the bug, but not on purpose. The empty string still returns 1.
Edge cases on purpose
The idea: Lists the cases first: empty, one character, all the same, the longest run at the start, in the middle and at the end. “abbb” shows a run at the end is never counted; “” returns 1, not 0.
def longest_run(s): if not s: return 0 best = run = 1 for i in range(1, len(s)): run = run + 1 if s[i] == s[i - 1] else 1 best = max(best, run) return best- Bugs found
both- Cases tried
six, chosen- Why
- Updating best on every step means the last run is counted, and an empty string returns 0.
4. Ten minutes left (hard)
Section titled “4. Ten minutes left (hard)”You’re halfway through the optimal solution with 10 minutes left. The helper that does the tricky part isn’t written yet. What do you do?
Hint 1 of 2
What does the interviewer need to see in the last 10 minutes?
Hint 2 of 2
Could a working simpler version, plus a clear plan, score better than half of the best one?
Show the answers
Types faster, says nothing
The idea: Rushes the helper in silence and runs out of time mid-line.
- At the end
nothing runs- Interviewer knows
little- Why
- No working code, no test, and no idea what you planned.
Finishes, untested
The idea: Writes the helper quickly and says “I think that works.”
- At the end
code that may run- Interviewer knows
some- Why
- Better, but a bug in the rushed helper is likely and nobody has checked.
Say the plan, finish the core, test it
The idea: “I have 10 minutes. I'll write the main function with the helper as a stub. I'll explain what the helper does and its cost, then test the main path.” Fills in the helper if time remains.
- At the end
a tested main path- Interviewer knows
the whole plan- Why
- The interviewer sees working, tested code, knows exactly what's missing, and sees calm time management, which is part of the score.
Check yourself
Section titled “Check yourself”A few quick questions. Ones you miss are remembered, so you can find your weak spots later.
Flashcards
Section titled “Flashcards”Add these to your review deck. Each card comes back a little later every time you get it right.
Cheat sheet
Section titled “Cheat sheet”- The steps: clarify, examples, brute force, optimize, code, test, analyze. Out loud.
- A 45-minute round: about 4 minutes to clarify, 3 for examples, 6 for brute force and optimizing, 12 to 15 to code, 6 to test, 2 to analyze.
- Ask what changes the code: order, ties and boundaries, empty, size, return value, may I change the input.
- Brute force first, with its cost. Then name the slow part and remove it.
- Agree on the plan before you code: “Shall I code that?”
- Test on purpose: a walk-through, then empty, one, all the same, none, all, the boundary, big.
- Stuck: say what you know, try a smaller example, ask a specific question.
Go deeper
Section titled “Go deeper”- Two Sum: the same method on the most common first question, with a brute force, a hash map and two pointers.
- Count errors in a 10 GB log: what “it doesn’t fit in memory” changes, a follow-up you’ll hear often.
- The lesson’s code:
content-code/playbook/coding-round/in this site’s repository, with all three candidates and the tests that show exactly where the weak one fails.
Can you do these now?
If you’re not sure of any of these, scroll back to that part before moving on.
Status: Not started