Skip to content

Example report

Sample data for a fictional student, from a scripted interview. The report was written by the same pipeline that writes yours.

Coding mock interview on a weak day: an example feedback report

Software Engineering (Python), regular level, two problems, the first not solved in time, Oct 23, 2026

Below the bar

If you read nothing else

Not yet at the Regular bar: the gaps below matter most.

  • Strength: Your complexity arithmetic was solid once prompted — converting 10^14 operations into roughly eleven days was exactly the right move.

    Ten to the fourteen over ten to the eight... is ten to the six. A million seconds.Your words, 29:38
  • Gap: Fix the sliding-window left pointer. Your window idea was right, but the left pointer could move backwards, so 'abba' gave 3 instead of 2.

    Then a at three, a was at zero, so left goes to... one? That moves left backwards.Your words, 20:41
  • Gap: Predict outputs before you run. You wrote the first version and only then discovered four failures at once, and 'abba' surfaced only when the interviewer named it.

    Okay. I think that's it. Let me run it.Your words, 9:01

One moment from your delivery

You hesitated and used hedging phrases

When asked “It is. Can you do better than that?” (Q1), you hesitated and used hedging phrases: you took 13.0 s to start (your usual 5.0 s); a 3.4 s pause mid-answer; your pace ranged from 3.0 to 5.8 syllables per second; 4 hedges such as 'Maybe'; 2 restarted sentences.

  • Time to start 13.0 s vs your usual 5.0 s
  • Longest pause 3.4 s
  • Your pace swung 68% vs your usual 40% (3.0 to 5.8 syllables/s)
  • Hedging 4 (“Maybe”, “kind of”, “I'm not sure”)
  • Restarted sentences 2
I've seen sliding window for this kind of problem, but I don't remember exactly how it goes.Your words, 4:02

Try: Start with a one-line headline ('My approach is X because Y') and think aloud from there instead of in silence.

Your next task, 20 min

Fix the sliding-window left pointer

Implement longest substring without repeating characters from scratch. First trace 'abba' and 'pwwkew' on paper, write your left-pointer rule, then code and run both plus an empty line.

What happened

You worked through two problems: longest substring without repeating characters, then two-sum. You got a working brute-force two-sum and a sliding window that passed most examples, but the abba case and the empty input stayed broken. Your main takeaway: trace small cases on paper before coding, and finish one fix before switching approaches.

Below the bar

For the Regular level, this performance is below the bar.

You answered all 2 planned questions.

After that

More ways to practice, in order of impact

  1. 1

    Predict outputs before you run: Before running any solution, write three inputs on paper — empty, all-same-character, and one repeat after a gap — and predict the output for each. 10 minutes.

  2. 2

    Retry the same questions and compare your result with this one.

Scorecard

Each skill from the rubric, scored 1 to 5, with the moments it was based on

  • Get to a correct solution before optimising, and when a hint lands, finish the fix in code rather than describing it. The abba fix was one line: left = max(left, seen[ch] + 1).

    Maybe a window? I've seen sliding window for this kind of problem, but I don't remember exactly how it goes.Your words, 4:02
    I don't know. Maybe only move left if... the old position is inside the- inside the window?Your words, 21:34

    What good looks like: Reaching the sliding window independently and stating the rule "move left to the later of its current spot and last-seen plus one" before coding, then reusing the hash-map idea for two-sum in one pass.

    To reach 3: reaches a correct but unoptimized approach with some help.

    Before coding, write the invariant on one line and dry-run two tricky inputs against it.

  • Main cases work, but two known bugs were left in the code. Before saying you're done, re-read the loop bounds and the input parsing — both bugs were visible in the code itself.

    That moves left backwards. So the window is from one to three, that's three. That's wrong.Your words, 20:41
    Because... the line is empty, so split gives an empty list, and then zero is out of range.Your words, 19:54

    What good looks like: Code that passes every example including an empty line, where left never moves backwards and the input is guarded before indexing.

    To reach 3: works on the main case with small bugs.

    Add an empty-input guard and clamp left with max(left, seen[ch] + 1) in your next sliding-window attempt.

  • Your analysis is correct once you're pushed, but you should size the input before choosing an approach, and state space complexity in terms of the alphabet or n from the start.

    So, um... n squared times... the length of the substring. Which is up to n. So n cubed?Your words, 3:35
    As many as... the different characters. So, um, not O(1) then. O(n)?Your words, 22:52

    What good looks like: Naming the space cost as O(min(n, alphabet)) without prompting, and saying why the hash-map two-sum drops time from O(n^2) to O(n).

    To reach 5: precise analysis and identifies better alternatives and their trade-offs.

    After each solution, say time and space out loud and justify the space bound by naming what grows.

  • Before running, write down three cases of your own — empty, all-same, and a case with a repeat after a gap like abba — and check each result against a hand trace, not just pass/fail.

    Um, the empty one, which crashes. And a b b a, which is wrong.Your words, 23:17
    Because... the second 3 overwrote the first one in the dictionary? So it found index one. I think that was lucky, again.Your words, 32:36

    What good looks like: Listing edge cases (empty line, single character, all-same, abba) before running, and checking whether a passing example passes for the right reason.

    To reach 5: proactively builds test cases, finds own bugs.

    Before running, write three test inputs on paper: empty, one character, and a case where the window shrinks.

  • Your narration is a real asset. Add a short clarifying phase at the start of each problem — input format, empty input, character set — before you commit to an approach.

    Okay. Um, can I use the same number twice? Like if the target is 6 and there's a 3?Your words, 24:40
    So I read the line, and take the first word, with split... then the dictionary, seen... left is zero, best is zero...Your words, 7:09

    What good looks like: Asking about character set and empty input up front, then narrating each pointer move while coding instead of only when asked.

    To reach 5: narrates reasoning, asks good clarifying questions, structured throughout.

    Ask two clarifying questions at the start of every problem, then say each step aloud while typing.

Also went well

  • You thought out loud throughout, which made your reasoning easy to follow and to correct.
  • You debugged methodically with print statements and hand traces, and you were honest when a result was luck rather than correctness.

Also to improve

  • Finish the fix instead of describing it: the abba bug and the two-sum self-pairing both had one-line fixes you identified but never ran.
  • Hand-trace the algorithm on a tricky case before writing code — the off-by-one and the backwards left pointer would both have shown up.
  • Handle input edge cases (empty line, spaces) as part of the solution, not as an afterthought.

What an interviewer might worry about

  • Twice you accepted passing examples without checking why they passed, and both times they were passing by accident.
  • You claimed O(1) space for a dictionary that grows with the input.
  • When stuck you offered to fall back to brute force rather than pushing on the window fix.

Question by question

Open a question to see which key points you covered, in your own words, and what a stronger answer sounds like.

  1. Your answer: You started with a brute force over all substrings and costed it at O(n^3), then moved to a sliding window with a dictionary of last positions. The length was off by one, a detour through len(seen) passed two examples by luck, and after reverting the window still moved backwards on a b b a and crashed on empty input.

    Key points

    • Sliding window with last-seen map and left pointer (Partly)

      I think you keep a dictionary of where you last saw each- each character, and a left pointerYour words, 4:02

      Left should be max(left, last position + 1) so it never moves backwards; on a b b a your rule jumped left back to 1.

    • O(n) time, space bounded by distinct characters (Partly)

      not O(1) then. O(n)? Or the size of the alphabet, like, all the ASCII charactersYour words, 22:52

      The dictionary holds at most one entry per distinct character, so space is O(min(n, alphabet)), not O(1).

    • Brute force over all substrings is O(n^3) (Covered)

      So, um... n squared times... the length of the substring. Which is up to n. So n cubed?Your words, 3:35
    • Edge cases: empty, all same, all distinct (Partly)

      Because... the line is empty, so split gives an empty list, and then zero is out of range.Your words, 19:54

      Also try a string where every character is different, and one containing spaces, since the input can be any ASCII.

    Follow-up questions

    • the cost of checking each substring Handled wellYou immediately corrected n squared to n cubed once the set-building cost was pointed at.
    • whether you could do better than n cubed Partly handledYou named the sliding window and the last-seen dictionary but weren't sure where left should move.
    • to count the characters from left to i inclusive Partly handledYou said two before counting zero, one, two and finding three.
    • what happens to seen entries that leave the window Partly handledYou spotted that stale entries made len(seen) too big but had no fix for removing them.

    A stronger answer

    First I'd check the input: the string can be empty and can contain spaces, so I'd read the whole line and print 0 for the empty case. Then I'd keep a dictionary from character to the last index where I saw it, a left pointer for the start of the window, and a best counter. For each index i and character ch, if ch is already in the dictionary and its last position is at or after left, I move left to that position plus one, written as left = max(left, seen[ch] + 1) so left never moves backwards. Then I set seen[ch] = i and update best with i - left + 1. On a b b a that gives: at the last a, its old position 0 is before left, so left stays at 2 and the window is b a, length 2, which is correct. Time is O(n) because each character is processed once, and space is O(min(n, alphabet)) for the dictionary.

    Common mistakes on this question

    • Computing the window length as i - left and forgetting the +1, which makes every answer one too small.
    • Moving left to last position + 1 without taking the max, so left can jump backwards on input like a b b a.

    Hints used: 1

  2. Your answer: You wrote the two-loop brute force, fixed the self-pairing by starting j at i + 1, and all four examples passed. For the ten-million-element version you built a value-to-index dictionary but inserted everything first, so 3 paired with itself; you described the fix but didn't run it, and the sorted two-pointer follow-up stayed shaky.

    Stayed general

    No concrete example.

    I'm not sure how to explain it. It just moves towards the target?Your words, 34:50

    Try: Walk through 2, 7, 11, 15 with target 9 and say why moving the right pointer when the sum is too big can never throw away the only valid pair.

    Key points

    • Brute force is O(n^2) time, O(1) space (Covered)

      Two loops, so n squared. Space is nothing extra.Your words, 25:43
    • One pass with value-to-index map, O(n) (Partly)

      So I put all the numbers in a dictionary with their index, and then for each number I look up target minus it.Your words, 30:13

      Do it in one pass: look up target - x before you insert x, so the map only ever holds earlier elements.

    • Check complement before inserting to avoid self-pairing (Partly)

      So I'd need to check that j isn't i.Your words, 32:06

      Checking the complement before inserting means a value can never find its own index, so 3 2 4 with target 6 gives 0 2.

    • Duplicates, negatives, no solution, tiny inputs (Partly)

      Because... the second 3 overwrote the first one in the dictionary? So it found index one.Your words, 32:36

      Duplicates like 3 3 need two separate indices in the map; also test no solution and a single-element array.

    Follow-up questions

    • why the brute force printed 0 0 Handled wellYou saw at once that j started at 0 and paired the element with itself.
    • roughly how long n squared takes at a hundred million operations a second Handled wellYou converted ten to the fourteen into about a million seconds, over a week.
    • what went wrong in the dictionary version Partly handledYou found the self-lookup but only described the j != i fix without running it.
    • to run two pointers on 2, 7, 11, 15 with target 9 Partly handledYou found the right moves by trial but weren't sure of the rule for the too-small case.

    A stronger answer

    First I'd confirm the constraints: exactly one pair, the same element can't be used twice, and the array can be unsorted with negatives and duplicates. Since there can be up to ten million elements, the two nested loops are too slow, around ten to the fourteen operations, so I'd use a dictionary from value to index. I'd go through the array once: for each number x at index i, I first check whether target - x is already in the dictionary, and if it is I print that index and i and stop. Only after that check do I store pos[x] = i, so a number can never be paired with itself, and for 3 3 with target 6 the second 3 finds the first one. That's O(n) time and O(n) space. For the sorted, O(1)-space variation I'd use two pointers, one at each end: if the sum is too big I move the right pointer left, if it's too small I move the left pointer right, and that can't skip the pair because the array is sorted.

    Common mistakes on this question

    • Starting the inner loop at 0 instead of i + 1, so an element gets paired with itself and you print 0 0.
    • Building the whole hash map first and then looking up, which lets a value match its own index.

    Hints used: 1

Your code, each issue with the line it is about, and the complexity you said against the actual one.

1Given a string, find the length of the longest substring without repeating characters.

Your code, sent at 19:20

s = input().split()[0]seen = {}left = 0best = 0for i in range(len(s)):    ch = s[i]    if ch in seen:        left = seen[ch] + 1    seen[ch] = i    best = max(best, i - left + 1)print(best) 
  • Bugline 8Your left pointer can jump backwards. When the repeated character's last position is already behind the window (the a b b a case), seen[ch] + 1 is smaller than the current left, so the window grows over characters it should have dropped and you report 3 instead of 2.

    left = seen[ch] + 1

    Fix: Only ever move left forward: left = max(left, seen[ch] + 1). Once left never moves backwards, the stale entries you were worried about in seen become harmless, so you don't need to delete anything.

  • Bugline 1Reading the input with split()[0] crashes on an empty line (IndexError) and silently cuts the string at the first space, so any string containing a space is only partly processed.

    s = input().split()[0]

    Fix: Read the whole line, e.g. s = input().rstrip("\n"), and handle the empty case first: if not s: print(0) and stop.

Complexity: time O(n), space O(min(n, alphabet)) · differs from what you said

Your O(n) time is right, but the dictionary is not O(1) space — you corrected this yourself at turn 60.

Edge cases to check

  • empty input line: your code raises an IndexError instead of printing 0
  • a string containing a space, e.g. "ab cd": split()[0] throws away everything after the first space, so the answer is computed on the wrong string
  • "abba": your code prints 3 instead of 2 because left moves backwards; keep this as a regression test once you add max()

A cleaner outline

  1. Read the whole line as-is; if it is empty, print 0 and stop.
  2. Keep a dict from character to its last index, a left pointer at 0 and best at 0.
  3. For each right index, if the character's last index is at or after left, set left to that index + 1 — never let left decrease.
  4. Store the character's new index and update best with right - left + 1.
  5. Print best.

2Given an array of integers and a target value, return the indices of two numbers that add up to the target.

Your code, sent at 31:26

n = int(input())nums = list(map(int, input().split()))target = int(input())pos = {}for i in range(n):    pos[nums[i]] = ifor i in range(n):    j = pos.get(target - nums[i])    if j is not None:        print(i, j)        break 
  • Bugline 8You look up the complement without checking that it is a different index, so an element can be paired with itself: for 3 2 4 with target 6 you print 0 0.

    j = pos.get(target - nums[i])

    Fix: Add the index check (j is not None and j != i), or better, switch to one pass that looks up the complement before inserting the current element — then a stored index is always earlier than i and self-pairing cannot happen.

  • Riskline 6Building the whole map first means only the last index of a duplicated value survives, which is why the 3 3 case passed by luck rather than by design.

    pos[nums[i]] = i

    Fix: Insert as you scan instead of pre-filling: check target - nums[i] against the map, then store nums[i] = i. Each value then keeps the earliest usable index and duplicates behave predictably.

Complexity: time O(n), space O(n) · matches what you said

Correct: two separate passes are still linear, and the map holds up to n entries.

Edge cases to check

  • negative numbers, e.g. -3 4 3 with target 0: you never ran a case with negatives, so nothing confirmed the map handles them
  • 3 5 with target 6: the smallest input that shows the self-pairing bug; worth keeping as a regression test

A cleaner outline

  1. Read n, the numbers and the target.
  2. Create an empty dict from value to index.
  3. Loop once over the array: compute need = target - nums[i].
  4. If need is already in the dict, print that stored index and i (smaller first) and stop.
  5. Otherwise store nums[i] = i and continue — checking before inserting is what stops an element pairing with itself.

Your code runs

25 runs, 14 of 24 example checks passed, 3 ended in an error. Last run: passed.

Measured by the code runner, not judged

  • 113 runs, 5 of 12 example checks passed, 3 ended in an error
  • 212 runs, 9 of 12 example checks passed

Coaching

The few changes that matter most, with a way to practice each one

  1. 1Code quality and correctness

    Fix the sliding-window left pointer

    Your window idea was right, but the left pointer could move backwards, so 'abba' gave 3 instead of 2. You traced it correctly and then had no rule to repair it, which is where most of the first problem's time went.

    Then a at three, a was at zero, so left goes to... one? That moves left backwards.Your words, 20:41

    How to practice: On paper, trace 'abba' and 'pwwkew' with a left pointer and a last-seen map. Write the rule for moving left so it never goes backwards, then code it and run both cases. 20 minutes.

  2. 2Testing and edge cases

    Predict outputs before you run

    You wrote the first version and only then discovered four failures at once, and 'abba' surfaced only when the interviewer named it. A short hand-trace first would have caught the off-by-one and the empty-input crash before running.

    Okay. I think that's it. Let me run it.Your words, 9:01

    How to practice: Before running any solution, write three inputs on paper — empty, all-same-character, and one repeat after a gap — and predict the output for each. 10 minutes.

  3. 3Complexity and optimization

    Name the variable in space bounds

    You called the dictionary O(1) space and then were unsure how large it could grow. Saying 'O(k) where k is the number of distinct characters' shows you know the bound instead of guessing.

    It's one loop, so O(n). And space is O(1), it's just a dictionary.Your words, 22:36

    How to practice: For every solution you write this week, say the space bound out loud as 'O(k) where k is ...' and name exactly what k counts. 10 minutes.

  • It's one loop, so O(n). And space is O(1), it's just a dictionary.Your words, 22:36

    The loop runs once, so O(n) time. The dictionary holds at most one entry per distinct character, so O(k) space where k is the number of distinct characters, which is at most n.

    Naming k shows you know what the bound depends on instead of calling it constant.

  • Um. I don't know. Maybe only move left if... the old position is inside the- inside the window?Your words, 21:34

    I'd guard the move: left becomes the larger of its current value and the last position of this character plus one, so it can never go backwards.

    You had the right instinct; stating it as a rule makes it sound like a decision, not a guess.

  1. Day 1Trace 'abba' and 'pwwkew' on paper, write the left-pointer rule20 min
  2. Day 2Code longest substring from scratch, run empty and 'pwwkew'20 min
  3. Day 3Rest, or reread your left-pointer notes for five minutes5 min
  4. Day 4Two sum with a dictionary in one pass, check j is not i20 min
  5. Day 5Before coding anything, write three edge cases and predict outputs15 min
  6. Day 6Rest day
  7. Day 7Timed 25-minute mock: one sliding window problem, narrate out loud25 min

Pace, pauses, fillers and pitch, measured from your voice. Signals, not judgments.

Moments worth a look

  • You hesitated and used hedging phrases

    When asked “It is. Can you do better than that?” (Q1), you hesitated and used hedging phrases: you took 13.0 s to start (your usual 5.0 s); a 3.4 s pause mid-answer; your pace ranged from 3.0 to 5.8 syllables per second; 4 hedges such as 'Maybe'; 2 restarted sentences.

    • Time to start 13.0 s vs your usual 5.0 s
    • Longest pause 3.4 s
    • Your pace swung 68% vs your usual 40% (3.0 to 5.8 syllables/s)
    • Hedging 4 (“Maybe”, “kind of”, “I'm not sure”)
    • Restarted sentences 2
    I've seen sliding window for this kind of problem, but I don't remember exactly how it goes.Your words, 4:02

    Try: Start with a one-line headline ('My approach is X because Y') and think aloud from there instead of in silence.

  • You hesitated and used hedging phrases

    When asked “How would you stop that?” (Q1), you hesitated and used hedging phrases: you took 14.0 s to start (your usual 5.0 s); a 3.6 s pause mid-answer; 3 hedges such as 'I don't know'.

    • Time to start 14.0 s vs your usual 5.0 s
    • Longest pause 3.6 s
    • Hedging 3 (“I don't know”, “Maybe”, “I'm not sure”)
    Maybe only move left if...Your words, 21:34

    Try: Start with a one-line headline ('My approach is X because Y') and think aloud from there instead of in silence.

  • You stayed general

    When asked “Why can't that skip the right pair?” (Q2), your answer stayed general: no concrete example.

    • Stayed general
    I'm not sure how to explain it. It just moves towards the target?Your words, 34:50

    Try: Walk through 2, 7, 11, 15 with target 9 and say why moving the right pointer when the sum is too big can never throw away the only valid pair.

Voice signals

Measured in 45 of 52 answers with audio.

  • Your volume dropped at the end of 1 of 45 measured answers (6 dB or more over the last 1.5 s).
  • Your pitch stayed within 3 semitones in 0 of 45 measured answers.
  • Your pitch went up at 26 of 237 measured phrase endings.
  • Your pace changed by 60% or more within 1 of 33 answers long enough to measure.

7 of 52 answers did not have enough clear audio to measure (background noise, too little speech).

You hedged five times in one answer; state the approach as a decision first, then flag the single part you're unsure of.

Ask one clarifying question about input size or character set before coding; the empty-input crash only came up after a prompt.

Pace, pauses and fillers

Measured across 54 answers: average speaking rate 119 wpm, 2.6 fillers per speaking minute, average time to start answering 5.0 s, longest mid-answer pause 3.6 s.

Pace
119words/min
Fillers
2.6per min
Longest pause
3.6s
Time to first word
5.0s
Average before you started answering
Speaking time
76%
Share of answer time spent speaking
Hedges
45
Phrases like "I think" or "maybe"

Answer by answer

Pause Strong Hesitation Rushing Trailing off Rambling

The answers with a marked moment. Notes on single answers use typical speaking ranges.

Question 1

  • 0s45s
    Length
    45s
    Pace
    126
    To first word
    6.5s
    Fillers
    2
    Hedges
    2
    Pauses
    0
    • Hesitation (0s to 17s): Start came after 6.5 s, with 2 fillers and 2 hedge phrases in the answer.
  • 0s22s
    Length
    22s
    Pace
    116
    To first word
    5.0s
    Fillers
    1
    Hedges
    1
    Pauses
    0
    • Trailing off (17s to 22s): Voice level over the last 5 s was about 8 dB lower than earlier in the answer.
  • 0s55s
    Length
    55s
    Pace
    118
    To first word
    13.0s
    Fillers
    2
    Hedges
    5
    Pauses
    1
    • Hesitation (0s to 23s): Start came after 13.0 s, with 2 fillers and 5 hedge phrases in the answer.
  • 0s48s
    Length
    48s
    Pace
    117
    To first word
    6.5s
    Fillers
    2
    Hedges
    1
    Pauses
    1
    • Hesitation (0s to 17s): Start came after 6.5 s, with 2 fillers and 1 hedge phrase in the answer.
  • 0s41s
    Length
    41s
    Pace
    108
    To first word
    1.1s
    Fillers
    1
    Hedges
    0
    Pauses
    0
    • Trailing off (31s to 41s): Voice level over the last 10 s was about 8 dB lower than earlier in the answer.
  • 0s40s
    Length
    40s
    Pace
    119
    To first word
    5.9s
    Fillers
    1
    Hedges
    3
    Pauses
    1
    • Hesitation (0s to 16s): Start came after 5.9 s, with 1 filler and 3 hedge phrases in the answer.
    • Trailing off (31s to 40s): Voice level over the last 9 s was about 8 dB lower than earlier in the answer.
  • 12 steady stretches noted.
  • 9 hesitation episodes noted.
  • 19 trailing-off endings noted.

What Vera wrote down while listening

  1. GapQuestion 12:35

    No clarifying questions (character set, empty input).

  2. GapQuestion 12:47

    Brute force costed as n^2; checking each substring was not counted until Vera said so.

  3. GapQuestion 19:00

    Length computed as i - left (off by one); input().split()[0] crashes on an empty line.

  4. GapQuestion 112:56

    Counted the window 0..2 as two characters; needed a second prompt.

  5. GapQuestion 114:58

    Switched to len(seen): passes two examples by accident, wrong on pwwkew.

  6. ClaimQuestion 115:54

    Saw that stale entries stay in seen after Vera pointed at them; no fix.

  7. ClaimQuestion 119:20

    Reverted to i - left + 1: three examples pass, empty input still crashes.

  8. GapQuestion 120:41

    Found by tracing that left moves backwards on abba; could not fix it.

  9. GapQuestion 122:36

    Claimed O(1) space for the dictionary; unsure when asked how big it gets.

  10. GapQuestion 227:08

    Two sum brute force paired an element with itself; two examples failed.

  11. GapQuestion 228:34

    Did not consider the stated ten-million size until reminded.

  12. GapQuestion 231:26

    Map version inserts everything first and pairs 3 with itself; fix described but not run.

  13. GapQuestion 233:20

    Sorted follow-up: proposed binary search; did not remember the two-pointer rule, unsure after a trace.

Three more notes

More next steps

  • Sliding window: Left should be max(left, last position + 1) so it never moves backwards; on a b b a your rule jumped left back to 1.
  • Sliding window: The dictionary holds at most one entry per distinct character, so space is O(min(n, alphabet)), not O(1).
  • You hedged five times in one answer; state the approach as a decision first, then flag the single part you're unsure of.

107 turns, word for word

  1. Vera0:02

    Hi, I'm Vera. Thanks for joining. This is the coding round, about forty-five minutes, and we'll try to do two problems. There's an editor on the right, and you can run your code against the examples as often as you like. Please think out loud while you work; if you get stuck, tell me what you're thinking. Before we start, what are you working on these days?

  2. You0:27

    Um, hi. So I'm finishing my degree, it's my last year. Right now it's mostly coursework, and, uh, I'm in a group project where we build a small web app for a student club, for their events and sign-ups. I do the front end mostly, React, and a bit of the API. I haven't done that many of these kinds of problems, to be honest, I started practising like two weeks ago. So I'm a bit nervous.

  3. Vera1:09

    No rush, take a moment. What's the part of the app you're happiest with?

  4. You1:14

    Um, probably the sign-up form. It checks if the event is full and shows a waiting list, and it updates without reloading the page. It took a while because the count was sometimes wrong when two people signed up at the same time. I think someone else fixed that part in the backend, actually, I'm not totally sure how. But the form itself is mine, and the styling.

  5. Vera1:51

    Okay. Let's start. First problem. Given a string, find the length of the longest substring without repeating characters. The string comes on one line of standard input; print one number. For example, for a b c a b c b b the answer is 3, the substring a b c. The other examples are on the right.

  6. You2:13

    Okay. So the longest part of the string where no letter repeats. And it has to be, um, next to each other, a substring, not like, picking letters from different places.

  7. Vera2:32

    Right, contiguous. Any questions before you start?

  8. You2:35

    Um, no, I think it's clear.

  9. Vera2:41

    Okay. How would you approach it? Talk me through the idea before any code.

  10. You2:47

    Okay, um. I'd check every substring and see if it has repeats. Like, two loops, i and j, and the substring from i to j, and I put it in a set, and if the set is the same size as the substring, there are no repeats. And I keep the longest one I find. Um, there are n squared substrings, so it's n squared. Which is, I think, okay-ish? I don't know how long the strings are.

  11. Vera3:33

    Checking each substring also costs something.

  12. You3:35

    Oh, right, building the set. So, um... n squared times... the length of the substring. Which is up to n. So n cubed? That seems like a lot. Yeah. That's probably too slow.

  13. Vera3:59

    It is. Can you do better than that?

  14. You4:02

    Hmm. Maybe a window? I've seen sliding window for this kind of problem, but I don't remember exactly how it goes. I think you keep a dictionary of where you last saw each- each character, and a left pointer, and you move the right side one by one. And when there's a repeat, you, um, move the left pointer. I'm not sure exactly where to. Maybe to the repeat? Or, wait, after it.

  15. Vera4:57

    Walk me through it on the example first, a b c a b c b b.

  16. You5:05

    Okay, um. I go a, b, c, those are all new, I put them in the dictionary at zero, one, two. Then a again, and a is in the dictionary at zero, so left moves to one. Then, um, the length is i minus left. And I keep the best. Then b is at one, so left goes to two, and so on. I think that's it. The best is three at some point.

  17. Vera5:54

    And for b b b b b, what does your rule give?

  18. You6:00

    b at zero. Then b again, it's at zero, so left goes to one. Then b at two, left goes to two. So left follows i, and the window is, um, one character. So one. Which is right, I think.

  19. Vera6:27

    Okay. What's the complexity of that?

  20. You6:29

    One loop, so O(n). I think. The dictionary lookups are constant, I think.

  21. Vera6:41

    Okay, go ahead and code it. Keep talking while you write.

  22. You7:09

    So I read the line, and take the first word, with split... then the dictionary, seen... left is zero, best is zero... for i in range of the length... I'm, uh, just writing the loop. If the character is in seen, left is the old position plus one. Then I store the position. Then best is the max of best and i minus left. And print best at the end.

  23. You9:00

    Sent to the workspace, python

    s = input().split()[0]seen = {}left = 0best = 0for i in range(len(s)):    ch = s[i]    if ch in seen:        left = seen[ch] + 1    seen[ch] = i    best = max(best, i - left)print(best) 
  24. You9:01

    Okay. I think that's it. Let me run it.

  25. You9:28

    Um, none of them pass. The first one gives 2 instead of 3. The second gives 0, it should be 1. The third one also gives 2. And the last one crashed, there's an index error. Hmm. Okay. That's not great.

  26. Vera9:51

    Start with the first one. What does your code do when it sees a character that's already in the window?

  27. You9:59

    It moves left to just after the old- the old position. That should be right, I think... Maybe the problem is that the dictionary is never cleared? Like, old letters stay in it, and then it thinks there's a repeat when there isn't. Um, but in the first example the letters are all in the window anyway. So I don't know.

  28. Vera10:40

    If you extend a window to the right and hit a repeat, what do you do with the left side?

  29. You10:48

    I move it past the repeat? That's what I'm doing, I think. I don't really see what's wrong with that part. Let me print what's happening at each step, then I can see the numbers.

  30. You11:42

    Sent to the workspace, python

    s = input().split()[0]seen = {}left = 0best = 0for i in range(len(s)):    ch = s[i]    if ch in seen:        left = seen[ch] + 1    seen[ch] = i    best = max(best, i - left)    print(i, ch, left, best)print(best) 
  31. You12:06

    Okay, so it prints i, the character, left and best. At i equals 0, best is 0. At i equals 2 the best is 2, but the window is a, b, c, that's three characters. Hmm. Then it stays at 2. I don't see it. Maybe the length should come from the dictionary instead, like, how many things are in it. That would be three there.

  32. Vera12:45

    Before you change it: how many characters are between left and i, inclusive, when left is 0 and i is 2?

  33. You12:56

    Between zero and two... that's, um, two. Two minus zero.

  34. Vera13:09

    Count them.

  35. You13:11

    Zero, one, two. Three. Oh. So it's plus one? But I'm not sure that's the whole problem, because the second one gives zero, and the crash is something else. I think using the dictionary is the cleaner way, then I don't need the left pointer for the length at all.

  36. Vera13:43

    Why would the size of the dictionary be the window length?

  37. You13:48

    Because, um, it has all the characters I've seen, and they're different, since it's a dictionary, the keys are unique. So the number of keys is the number of different characters. And the window has different characters. So I think that should be the window. I'll try it.

  38. You14:58

    Sent to the workspace, python

    s = input().split()[0]seen = {}left = 0best = 0for i in range(len(s)):    ch = s[i]    if ch in seen:        left = seen[ch] + 1    seen[ch] = i    best = max(best, len(seen))print(best) 
  39. You15:19

    Two pass now, the first and the second. The third one gives 4 instead of 3, and the empty one still crashes. I'm not sure why it's 4. p w w k e w, the longest is w k e, that's 3. Where does 4 come from?

  40. Vera15:46

    What happens to the entries in seen that are no longer in the window?

  41. You15:54

    They... stay in there. Oh. So the p is still in there when the window is w k e. So the length of seen counts characters that aren't in the window anymore. p, w, k, e, that's the 4. So I'd have to remove them when the window moves, but I'm not sure how to do that without another loop over the dictionary.

  42. Vera16:35

    So it passed two examples for the wrong reason.

  43. You16:43

    Yeah. I guess in a b c a b c b b there are only three letters anyway, so the dictionary never gets bigger than three. And b b b b b is one letter. So those two were, um, luck.

  44. You17:10

    Um, can I just do the brute force instead? So that at least something works, and then I can try to fix the window after?

  45. Vera17:36

    It's your call. What would it cost on a long string, say a hundred thousand characters?

  46. You17:46

    n cubed... a hundred thousand cubed is, um, ten to the fifteen. That's way too slow. Even n squared would be ten to the ten. Okay, no. I'll stay with the window.

  47. Vera18:13

    What are you thinking?

  48. You18:25

    Um, sorry. I'm thinking I'll go back to the first version and do the plus one, like with the counting. And keep the dictionary only for the positions. That at least fixes the first one.

  49. You19:20

    Sent to the workspace, python

    s = input().split()[0]seen = {}left = 0best = 0for i in range(len(s)):    ch = s[i]    if ch in seen:        left = seen[ch] + 1    seen[ch] = i    best = max(best, i - left + 1)print(best) 
  50. You19:38

    Three pass. Oh, the third one passes too now. The empty one still crashes, it's the same index error.

  51. Vera19:50

    Why does it crash?

  52. You19:54

    Because... the line is empty, so split gives an empty list, and then zero is out of range. I'd check for that first and print zero. Um, also I guess split would break the string if it has spaces in it, it would only take the first word. Should I fix it now?

  53. Vera20:28

    In a moment. Try the string a, b, b, a first. What should it print?

  54. You20:41

    a b b a. The answer is two, a b or b a. Let me trace mine. a at zero, b at one, best two. b again at two, b was at one, so left goes to two. Then a at three, a was at zero, so left goes to... one? That moves left backwards. So the window is from one to three, that's three. That's wrong. It should be two.

  55. Vera21:32

    How would you stop that?

  56. You21:34

    Um. I don't know. Maybe only move left if... the old position is inside the- inside the window? Or, like, delete things from the dictionary when left moves past them? But then I need a loop again, from the old left to the new left. I'm not sure how to write that. I don't think I'll get it right in the time we have.

  57. Vera22:31

    Okay. Let's leave the fix. What's the time and space complexity of what you have?

  58. You22:36

    It's one loop, so O(n). And space is O(1), it's just a dictionary.

  59. Vera22:48

    How big can the dictionary get?

  60. You22:52

    As many as... the different characters. So, um, not O(1) then. O(n)? Or the size of the alphabet, like, all the ASCII characters. I'm not sure which one you'd say.

  61. Vera23:13

    Okay. Anything else you'd want to test, given more time?

  62. You23:17

    Um, the empty one, which crashes. And a b b a, which is wrong. And maybe one long string, to see if it's fast. I can't think of others right now.

  63. Vera23:39

    One follow-up before we move on. How does it change if you need the substring itself, not just the length?

  64. You23:49

    Um, then when best changes, I'd also save where the window starts. So left, at that moment. And at the end I print the string from that start, for best characters. I think that works, if the window part is right, which, um, it isn't completely.

  65. Vera24:21

    Okay. We're about twenty-five minutes in, so let's move on. Second problem. Given an array of integers and a target value, return the indices of two numbers that add up to the target. Input: n, then the n numbers on one line, then the target. Print the two indices, smaller one first.

  66. You24:40

    Okay. Um, can I use the same number twice? Like if the target is 6 and there's a 3?

  67. Vera24:54

    No, the same element can't be used twice. Two different 3s are fine. Exactly one valid pair exists, and the numbers can be negative and unsorted.

  68. You25:05

    Okay. So, um, I was thinking, if it was sorted I could do something with two pointers, from both ends. But it's not sorted. And if I sort it, I lose where the numbers were. So, um, I'll just do two loops, try every- every pair, and print when they add up. That's the simplest. And then stop.

  69. Vera25:42

    Complexity of that?

  70. You25:43

    Two loops, so n squared. Space is nothing extra.

  71. Vera25:52

    Okay. Go ahead.

  72. You26:07

    So, read n, read the numbers, read the target. Two loops, i and j, both over the whole array. If they add up, print i and j and exit.

  73. You27:08

    Sent to the workspace, python

    n = int(input())nums = list(map(int, input().split()))target = int(input())for i in range(n):    for j in range(n):        if nums[i] + nums[j] == target:            print(i, j)            exit() 
  74. You27:30

    Two pass. The second one prints 0 0, and the one with 3 3 also prints 0 0.

  75. Vera27:42

    Why 0 0?

  76. You27:45

    Because, um, 3 plus 3 is 6, and it's the same 3, index zero twice. I use the same element, which you said I can't. So j has to start after i, not at zero. Then it also doesn't check pairs twice.

  77. You28:26

    Sent to the workspace, python

    n = int(input())nums = list(map(int, input().split()))target = int(input())for i in range(n):    for j in range(i + 1, n):        if nums[i] + nums[j] == target:            print(i, j)            exit() 
  78. You28:34

    All four pass now.

  79. Vera28:45

    The array can have up to ten million elements. How long does this take?

  80. You28:51

    Oh. Then n squared is... a lot. Ten million squared. Ten to the fourteen? I don't know how fast that is exactly, but it's too slow, I think. Um. Could I sort it? But then I lose the indices, like I said. Unless I keep them next to the numbers, maybe.

  81. Vera29:31

    Roughly how long, at a hundred million simple operations a second?

  82. You29:38

    Ten to the fourteen over ten to the eight... is ten to the six. A million seconds. That's, um, more than a week? Like eleven days. Okay, yeah, that's way too slow.

  83. Vera30:05

    Is there a data structure that answers "have I seen this value" in constant time?

  84. You30:13

    A dictionary. Or a set. So I put all the numbers in a dictionary with their index, and then for each number I look up target minus it. If it's there, that's the pair. Let me write it.

  85. You31:26

    Sent to the workspace, python

    n = int(input())nums = list(map(int, input().split()))target = int(input())pos = {}for i in range(n):    pos[nums[i]] = ifor i in range(n):    j = pos.get(target - nums[i])    if j is not None:        print(i, j)        break 
  86. You31:48

    Three pass. Example 2 prints 0 0 again. Hmm. 3 2 4, target 6.

  87. Vera31:58

    We're nearly out of time for this one. What's going on there?

  88. You32:06

    It looks up 6 minus 3, which is 3, and finds... itself, index zero. Same problem as before. So I'd need to check that j isn't i. I think that fixes it, but I'm not sure.

  89. Vera32:31

    And the 3 3 case passed. Why?

  90. You32:36

    Because... the second 3 overwrote the first one in the dictionary? So it found index one. I think that was lucky, again.

  91. Vera32:54

    And the complexity of this version?

  92. You32:57

    Um, two loops again, but not nested, so O(n)? And the dictionary is O(n) space.

  93. Vera33:11

    One last variation. What if the array is already sorted and you must use O(1) extra space?

  94. You33:20

    Then, um, I could do binary search? For each number, binary search for target minus it. That's n log n, and no dictionary. Or there's a two pointers thing, one at the start and one at the end, but I don't remember which one you move when. I've seen it, I haven't written it.

  95. Vera33:58

    Try it. Two pointers on 2, 7, 11, 15, target 9.

  96. You34:07

    Start is 2, end is 15, that's 17, too big. So I move... the start? Then 7 and 15, 22, bigger. Hmm, no. Then the end, maybe. 2 and 11, 13, still too big, then 2 and 7, 9. Okay, so the end moves when it's too big. I think. I'm not sure about the other case.

  97. Vera34:47

    Why can't that skip the right pair?

  98. You34:50

    Um... because... I'm not sure how to explain it. It just moves towards the target? I don't know how to show it doesn't skip it.

  99. Vera35:21

    Okay. We have a couple of minutes left. Any questions for me?

  100. You35:27

    Um, yeah. Is it normal to not finish? I feel like I ran out of time on both.

  101. Vera35:39

    Plenty of people don't finish every problem. What matters is how you get there, and the report goes through both problems step by step.

  102. You35:48

    Okay. And, um, what would you practise, if you were me?

  103. Vera35:57

    Your report will have specific suggestions based on this session. I'd rather not guess here.

  104. You36:03

    Okay. And, um, how long does the whole process usually take? Like, how many rounds?

  105. Vera36:15

    That depends on the role. The hiring team or the recruiter will have the schedule and the next steps.

  106. You36:22

    Okay. Thank you.

  107. Vera36:27

    Thanks for working through it. You'll get your report in a few minutes.

Mockich is a practice tool. Scores and delivery signals are guidance for your preparation, not a prediction of a real hiring decision.

Start another interview
Code runs in this session25 runs, 14 of 24 example checks passed

What the code runner returned to the student, in order: real executions of their code in the sandbox, on each question’s own data.

  1. 9:12Question 1Ran every example0/4 passed

    Python, the code sent at 9:00

    • 2
      

      Example 1: a string -> length: differs from the expected output.

      line 1, expected3yours2
    • 0
      

      Example 2: all the same: differs from the expected output.

      line 1, expected1yours0
    • 2
      

      Example 3: repeat inside the window: differs from the expected output.

      line 1, expected3yours2
    • No output.

      Edge: empty string (empty line): differs from the expected output.

  2. 11:47Question 1Ran with their own input ("abcabcbb")Ran

    Python, the code sent at 11:42

    0 a 0 0
    1 b 0 1
    2 c 0 2
    3 a 1 2
    4 b 2 2
    5 c 3 2
    6 b 5 2
    7 b 7 2
    2
    
  3. 15:03Question 1Ran every example2/4 passed

    Python, the code sent at 14:58

    • 3
      

      Example 1: a string -> length: matches the expected output.

    • 1
      

      Example 2: all the same: matches the expected output.

    • 4
      

      Example 3: repeat inside the window: differs from the expected output.

      line 1, expected3yours4
    • No output.

      Edge: empty string (empty line): differs from the expected output.

  4. 19:25Question 1Ran every example3/4 passed

    Python, the code sent at 19:20

    • 3
      

      Example 1: a string -> length: matches the expected output.

    • 1
      

      Example 2: all the same: matches the expected output.

    • 3
      

      Example 3: repeat inside the window: matches the expected output.

    • No output.

      Edge: empty string (empty line): differs from the expected output.

  5. 27:14Question 2Ran every example2/4 passed

    Python, the code sent at 27:08

    • 0 1
      

      Example 1: n, numbers, target -> two indices: matches the expected output.

    • 0 0
      

      Example 2: numbers not in order: differs from the expected output.

      line 1, expected1 2yours0 0
    • 0 0
      

      Edge: duplicate values: differs from the expected output.

      line 1, expected0 1yours0 0
    • 0 2
      

      Edge: negative numbers, target 0: matches the expected output.

  6. 28:31Question 2Ran every example4/4 passed

    Python, the code sent at 28:26

    • 0 1
      

      Example 1: n, numbers, target -> two indices: matches the expected output.

    • 1 2
      

      Example 2: numbers not in order: matches the expected output.

    • 0 1
      

      Edge: duplicate values: matches the expected output.

    • 0 2
      

      Edge: negative numbers, target 0: matches the expected output.

  7. 31:32Question 2Ran every example3/4 passed

    Python, the code sent at 31:26

    • 0 1
      

      Example 1: n, numbers, target -> two indices: matches the expected output.

    • 0 0
      

      Example 2: numbers not in order: differs from the expected output.

      line 1, expected1 2yours0 0
    • 0 1
      

      Edge: duplicate values: matches the expected output.

    • 0 2
      

      Edge: negative numbers, target 0: matches the expected output.