A wall chart for the coding interview

Mise en Place

In 2004 Michael Chu decided a recipe was a dependency graph and drew it as one: ingredients down the left, steps across the top, cells merging wherever two things combine. Twenty-two years later it is still the clearest way anyone has drawn a process. So here are the ten most-worn LeetCode problems, plated the same way.

10 dishes 1 notation 0 whiteboards
1 array grain what you were handed one step,
eating two
ingredients
a decision,
eating all three
the dish
1 counter n set to zero
1 stack rest empty; joins late
Every chart on this page is one of these. Hover a step to see what feeds it.

How to read the chart

It is a tiling, not a list. Read left to right, the way time runs. A cell spanning three rows is one step consuming all three of those ingredients at once.

The shape is the information. Cells side by side happen in sequence. Two cells in the same column are independent and can be done in either order.

Hatching means untouched. That ingredient is still on the counter. Once something enters the pan it never leaves, so hatching only ever appears on the left.

a step a decision the result not yet used

No.1

Two Sum

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

Method
One-pass hash map
Time
O(n)
Space
O(n)
Grade
Easy
1 arraynumsn integers, unsorted for i, x in enumerate(nums) c = target − x c in seen? yes → return [seen[c], i]
no → seen[x] = i, keep going
1 integertargetthe sum we are cooking toward
1 hash mapseenempty; keeps value → index

Chef's noteThe map is the mise en place: pay O(n) memory once so every lookup afterwards is free. Trading space for time is the whole dish.

No.2

Add Two Numbers

Given two non-empty linked lists whose digits are stored in reverse order, add the two numbers and return the sum as a linked list.

Method
Elementary column addition with a carry, poured onto a dummy head
Time
O(max(m, n))
Space
O(max(m, n))
Grade
Medium
2 listsl1, l2digits in reverse; once spent, val() reads 0 and nxt() None while l1 or l2 or carry s = carry + val(l1) + val(l2)
carry, d = divmod(s, 10)
tail.next = ListNode(d)
tail = tail.next
l1, l2 = nxt(l1), nxt(l2)
return dummy.next
1 carrycarrystarts at 0, never rises above 1
1 sentineldummyone throwaway node, made before the walk, discarded after dummy = ListNode()
tail = dummy
1 pointertailrests on dummy, walks right as digits land

Chef's noteThe carry is a third addend, so keep it in the while condition — a leftover 1 then writes its own digit instead of needing a special case. The dummy head buys the same relief on the other end: you never ask whether this is the first node.

No.3

Longest Substring Without Repeating Characters

Given a string, return the length of the longest substring that contains no repeated character.

Method
Sliding window over a last-seen index map
Time
O(n)
Space
O(min(n, k))
Grade
Medium
1 stringsn characters, taken left to right for r, ch in enumerate(s) ch in last and last[ch] ≥ left? yes → left = last[ch] + 1
no → left holds
last[ch] = r
best = max(best, r − left + 1)
loop ends
return best
1 hash maplastempty; keeps char → index last seen
1 pointerleftthe window's near edge, resting at 0
1 running maxbestseasoned to 0; the longest clean window

Chef's noteThe left edge never walks backwards: last[ch] says exactly where the window must resume, so both pointers only ever move forward and the whole string is tasted once. The guard last[ch] ≥ left is the seasoning that matters — without it a crumb from an already-discarded prefix drags the edge back and the count goes sour.

No.4

Median of Two Sorted Arrays

Given two sorted arrays, return the median of the two arrays combined, in logarithmic time.

Method
Binary search the partition of the shorter array
Time
O(log min(m, n))
Space
O(1)
Grade
Hard
2 sorted arraysA, Bswapped so A is the shorter; m ≤ n m, n = len(A), len(B)
if m > n: A, B, m, n = B, A, n, m
half = (m + n + 1) // 2
lo, hi = 0, m
while lo <= hi:
i = (lo + hi) // 2
j = half - i
aL = A[i-1] if i else -inf
aR = A[i] if i < m else inf
bL = B[j-1] if j else -inf
bR = B[j] if j < n else inf
aL > bR → hi = i - 1, loop
bL > aR → lo = i + 1, loop
else → the cut is right
L = max(aL, bL), R = min(aR, bR)
odd → return L
even → return (L + R) / 2
1 half measurehalf(m + n + 1) // 2 — how many go on the left plate
2 boundslo, hithe cut in A may fall anywhere from 0 to m
4 border tastesaL, aR, bL, bRthe values either side of each cut; −∞ off a left end, +∞ off a right
1 pinch paritym + n odd?one taste, or the average of two

Chef's noteNever merge the arrays — only decide where to cut them. Fixing j = half − i makes one cut decide both, so the dish reduces to a binary search for the cut where nothing on the left plate outranks anything on the right. Cutting the shorter array is not only for speed: it is what keeps j inside B, so swap the lengths along with the arrays.

No.5

Longest Palindromic Substring

Given a string, return the longest substring of it that reads the same forwards and backwards.

Method
Expand around every center
Time
O(n²)
Space
O(1)
Grade
Medium
1 stringsn characters, laid out in a single row n = len(s)
for i in range(n)
for l, r in ((i, i), (i, i+1)):
# the letter, then the seam to its right
while l >= 0 and r < n and s[l] == s[r]:
l -= 1; r += 1
span = r − l − 1 # both ends overshot span > len(best) → best = s[l+1:r]
after the last center, return best
2n − 1 centersievery letter, plus the n − 1 seams between them
2 pointersl, rseated on the center, then stepped outward in lockstep
1 running bestbestthe empty slice, until something beats it

Chef's noteA palindrome is defined by its middle, so taste outward from the 2n − 1 centers instead of boiling every substring. Each center is seeded twice — once on a letter, once on the seam to its right — because an even-length palindrome has no middle letter to stand on. The pointers always stop one step past the edge, and that overshoot is why the length is r − l − 1.

No.20

Valid Parentheses

Given a string of the characters ( ) [ ] { }, decide whether every bracket is closed by the right kind, in the right order.

Method
A stack of the closers you still owe
Time
O(n)
Space
O(n)
Grade
Easy
1 stringsn brackets, no other characters for ch in s ch in pairs? yes → expect.append(pairs[ch])
no → if not expect or expect.pop() != ch:
return False
loop survived →
return not expect
1 lookup tablepairsthree entries, opener → its closer
1 stackexpectempty; the closers still owed, newest on top

Chef's notePush the closer you owe, not the opener you saw - then every check is one plain equality instead of a table lookup. And the pan must come out empty: leftovers on the stack mean the dish was never finished.

No.21

Merge Two Sorted Lists

Given the heads of two sorted linked lists, splice their nodes into one sorted list and return its head.

Method
Two cursors stitched onto a dummy head
Time
O(m + n)
Space
O(1)
Grade
Easy
1 sorted listl1m nodes ascending; its own cursor, advanced as nodes are taken while l1 and l2 l1.val <= l2.val? yes → tail.next = l1; l1 = l1.next
no → tail.next = l2; l2 = l2.next
tail = tail.next
loop ends, one list spent
tail.next = l1 or l2
return dummy.next
1 sorted listl2n nodes ascending; walked alongside, never copied
1 sentineldummyone throwaway node, discarded before serving dummy = ListNode()
tail = dummy
1 pointertailrests on dummy, walks right as nodes land

Chef's noteThe sentinel is a greased pan: with a node already in hand, the first splice looks exactly like every other one, so no branch is ever spent asking whether the output is still empty. And when one cursor runs dry the survivor is still sorted — tip in the whole remainder rather than ladling it node by node.

No.53

Maximum Subarray

Given an integer array, find the contiguous subarray with the largest sum and return that sum.

Method
Kadane's running sum
Time
O(n)
Space
O(1)
Grade
Medium
1 arraynumsn integers, at least one; some will be bitter for x in nums cur = max(x, cur + x) best = max(best, cur) loop ends
return best
1 running sumcurbest tail ending at x; poured out the moment it sours cur = 0
1 running maxbestseasoned to −∞, never 0; tasted each pass, never lowered

Chef's noteNever carry a sour sauce forward: once the running tail goes negative it can only spoil whatever comes next, so cur drops it and restarts at x. Season best with −∞ rather than 0, or an all-negative array serves you an empty pan instead of its least bitter element.

No.121

Best Time to Buy and Sell Stock

Given the daily prices of a stock, return the largest profit from one buy and one later sell, or 0 if no trade turns a profit.

Method
Single pass over a running minimum
Time
O(n)
Space
O(1)
Grade
Easy
1 arraypricesn daily prices, served in order; never re-sorted for p in prices cheapest = min(cheapest, p) gain = p − cheapest
best = max(best, gain)
prices exhausted → return best
0 if no day ever rose
1 running minimumcheapestlowest price seen so far, not its day; seasoned to +∞
1 running maximumbestprofit banked so far; starts at 0

Chef's noteStanding on any day, cheapest already holds the whole past in one number, so a single subtraction values the best earlier purchase. Lower the floor before you weigh the sale and the worst case is a same-day trade worth 0 — which is why no clamp at the end is needed for a market that only falls.

No.206

Reverse Linked List

Given the head of a singly linked list, reverse the list and return the head of the reversed list.

Method
Three pointers walked forward
Time
O(n)
Space
O(1)
Grade
Easy
1 linked listheadn nodes, every arrow pointing forward curr = head while curr: nxt = curr.next curr.next = prev prev = curr
curr = nxt
↺ back to while
curr is None → list spent
return prev
1 pointercurrthe node on the board right now
1 pointernxtscratch; holds the rest of the list for one beat
1 pointerprevseasoned to None; becomes the new head

Chef's noteNever cut the forward arrow until nxt has hold of the rest of the list - that one scratch pointer is the entire recipe. prev trails one node behind curr, and prev is what you plate, not head: head is the tail once you are done, and it points at None.