Day 32 ยท Lining up the kids

Sorting

You will be able to
  • Implement insertion sort and merge sort from scratch and explain their complexities
  • Explain quicksort's partition idea and its O(nยฒ) worst case
  • Define stability and demonstrate why it matters for multi-key sorts
  • Explain why comparison sorting cannot beat O(n log n) and when counting sort escapes the bound
  • Apply the sort-then-solve pattern to simplify problems (merge intervals)
Today's ~120 minutes
Spaced-rep warm-up: due cards (graphs, heaps, Big O)10 min
ELI5 + tech read; run the sort-race visualizer on 3 input shapes18 min
Guided: implement & race, stability + counting sort + merge intervals38 min
Practice: meeting rooms20 min
Project: sorting field notes + eval-results sorter24 min
Quiz + flashcards10 min

Builds on: Day 22 โ€” Big O & complexity ยท Day 27 โ€” Recursion & divide/conquer

The analogy

A teacher lines up kids by height. The rookie method: take each kid and walk them backwards down the line until they slot in front of the first taller kid โ€” insertion sort. Fine for a small class; agonizing for a stadium, because each kid may shuffle past half the line (that is the nยฒ handshake feeling from Day 22).

The clever method: split the stadium into two halves, get each half lined up (however โ€” split again, recursively!), then MERGE: both lines face you, and you repeatedly wave forward whichever front kid is shorter. Merging two sorted lines is one easy pass โ€” that is merge sort, and the split-solve-merge shape is exactly Day 27's divide and conquer. Quicksort plays it differently: pick one kid (the pivot), send everyone shorter to the left and taller to the right, then repeat inside each side.

One more idea hides in plain sight: if two kids are the SAME height, does the line-up keep them in their original order? A method that does is called *stable* โ€” it sounds like trivia until you sort by height *and then* by age and discover only stable sorts let the two orderings compose.

Why this matters on the job

You will almost never implement a sort in production โ€” Python's Timsort has that covered โ€” but sorting is the interview's favorite complexity playground, and "sort first, then the problem becomes easy" is a genuinely load-bearing pattern: merge intervals, meeting rooms, deduplication, ranking eval results (Day 140), ordering retrieved chunks by score before reranking (Day 117). Stability bites for real: sort a DataFrame by date then by customer, and whether within-customer date order survives depends on the sort being stable. Knowing WHY the default sort is O(n log n) โ€” and when a counting sort beats it โ€” is the difference between using tools and understanding them.

Watch it happen

Lining up the kids โ€” insertion sort, card-player style

step 1 / 6
5
2
9
1
7
3
8

Insertion sort works like sorting a hand of cards: the left region is always sorted; take the next card and walk it left to its slot. One card (5) is trivially "sorted".

Guided practice

guided 1

Implement the three, race them

22 min
  1. Create sorting_lab.py. Implement insertion_sort (in place) and merge_sort (returns a new list) โ€” the starter gives merge scaffolding and a correctness checker against sorted().
  2. Implement quicksort with a RANDOM pivot in the simple three-way-list style shown.
  3. Race all three plus built-in sorted() on: random data (n = 2000), already-sorted data, reverse-sorted data. Before running, predict the ranking in each scenario and write it down.
  4. Explain your two most interesting results out loud โ€” expected: insertion sort wins on already-sorted (O(n)); a FIRST-element-pivot quicksort would die on sorted input (try it at n = 900 and watch for RecursionError โ€” why ~900? Python's recursion limit).
  5. Note how absurdly fast sorted() is โ€” C-speed Timsort. State when you would still hand-roll: never in production; always in interviews.
๐Ÿ python โ€” editable, runs in your browser
Ctrl/โŒ˜+Enter runs ยท Tab indents ยท numpy/pandas/sklearn auto-load on import (torch and network calls need a local run)
guided 2

Stability you can see + counting sort

16 min
  1. Build the starter's list of (name, grade) tuples. Sort by name first, then sort THAT result by grade using key=. Print it: within each grade, names are still alphabetical. That composition is stability at work โ€” Python guarantees it.
  2. Now shuffle and sort by grade in ONE pass with key=lambda p: (p[1], p[0]) โ€” the tuple-key trick. Confirm it matches the two-pass result, and note when each style wins (two stable passes when the sorts happen at different times/places; tuple key when you control one call).
  3. Implement counting_sort(scores) for exam scores 0โ€“100. Race it against sorted() on one million random scores. Say precisely why comparing was never necessary: the key space is tiny and known.
  4. Classic โ€” merge intervals (sort-then-solve): given [[1,3],[8,10],[2,6],[15,18]], merge overlaps. Think aloud: "Unsorted, every interval might overlap any other โ€” O(nยฒ) checks. Sorted by start, overlaps can only be adjacent: one linear pass, extending or appending." Implement and test with touching intervals like [1,4],[4,5].
๐Ÿ python โ€” editable, runs in your browser
Ctrl/โŒ˜+Enter runs ยท Tab indents ยท numpy/pandas/sklearn auto-load on import (torch and network calls need a local run)

On your own

Meeting rooms

20 min

Part 1: given meeting intervals, can one person attend them all? Part 2 (the real question): what is the MINIMUM number of rooms needed to host all meetings?

Constraints: aim for O(n log n); brute-force pairwise checking is disqualified. Test with back-to-back meetings ([1,5],[5,8] need one room) and a triple overlap.

Hints (only if stuck): Part 1 is merge-intervals thinking โ€” sort by start, look for any overlap between neighbors. Part 2 has two elegant solutions: (a) a min-heap (Day 30!) of room end-times โ€” reuse the room that frees earliest; (b) sort starts and ends separately and sweep with two pointers (Day 24). Implement one, understand both.

Ship before you stop

Sorting field notes + the eval-results sorter

Two parts in your practice repo. (1) dsa/sorting.py: today's implementations plus merge_intervals and meeting rooms, tested. (2) sort_evals.py, a taste of Day 140: given the provided CSV of mock eval results (columns: model, task, score, latency_ms), print a leaderboard sorted by score DESCENDING with latency ASCENDING as tiebreak โ€” one sorted() call with a clever key โ€” plus a per-task top-3 using the stable two-pass composition. Add a docstring explaining which sorts had to be stable and why. Commit both.

Rubric โ€” check what you completed (0/6)

Common mistakes & misconceptions

  • Writing comparison logic by hand when key= does it: sorted(rows, key=lambda r: (-r.score, r.latency)) beats any manual comparator.
  • Assuming quicksort is always O(n log n). Bad pivots (first element on sorted data) hit O(nยฒ); random or median-of-three pivots are the fix.
  • Forgetting merge sort's O(n) extra space when the interviewer asks "can you sort in place?" โ€” quicksort and heapsort can; classic merge sort cannot.
  • Believing O(n log n) is the floor for ALL sorting. It is the floor for COMPARISON sorting; counting/radix escape when keys are small integers.
  • Using strict < in a merge and silently losing stability โ€” equal elements must prefer the LEFT run (<=).
  • Sorting when a heap answers the actual question: "top 10 of a million" wants Day 30's O(n log k) heap, not an O(n log n) full sort.
Knowledge check

Q1. You sort employee rows by hire date, then stably sort by department. What is true of the result?

Q2. Why can no comparison sort beat O(n log n) in the worst case?

Q3. A million integer scores in 0โ€“100 need sorting. The strongest choice?

Go deeper โ€” curated resources

toolVisuAlgo โ€” Sorting race visualization โ†—20 minbookOpenDSA โ€” Sorting chapter โ†—25 mincourseCS50x Week 3 โ€” Algorithms (sorting segment) โ†—30 min
If you have a third hour
  • Timsort's run detection โ€” Timsort scans for pre-sorted "runs" and merges them cleverly. Skim the algorithm's description and connect it to why your already-sorted benchmark was near-instant.
Done means
  • All three sorts pass correctness checks; race results recorded and explained
  • Stability composition demonstrated and explained in your own words
  • Meeting rooms solved at O(n log n) with the approach named
  • Eval-results sorter committed with the stability docstring
  • Quiz โ‰ฅ 2/3
How this connects

โ† Back: Merge sort is Day 27's divide-and-conquer made concrete, the race harness is Day 22's timing lab, and meeting rooms reunites Day 30's heap with Day 24's two pointers.

Forward โ†’: Day 33 exploits what sorting buys: binary search only works on sorted data. Day 66's pandas sort_values inherits stability semantics, Day 117 sorts retrieved chunks by rerank score, and Day 140's eval reports are the leaderboard you just built, for real.

Unlocks: D33 Binary Search & Variants