Quicksort, Selection & Median of Medians

This deck covers quicksort's partition step and its recursion, the best, average, and worst-case running times, and the sorted input that triggers the worst case. It then explains randomized pivots and why they make the bad case vanishingly unlikely, introduces the selection problem and quickselect, and gives the median-of-medians pivot rule, using groups of five, that guarantees linear worst-case selection. It targets the myths that quicksort is always n log n, that selection requires a full sort, and that the choice of pivot does not matter for the worst case, and it explains why groups of five in particular are used.

Subject: CS3000 Algorithms · 135 slides · symbolic lesson

Open the interactive version of this deck · Homework for this lesson

What this lesson covers

The lesson, slide by slide

1. What you will be able to do

Objectives

Quicksort and its cousins are the workhorses behind most real sorting and ranking code. By the end of this lesson you can:

1. Explain the partition step and how quicksort recurses on the two resulting pieces.

2. State quicksort's best, average, and worst-case running times, and name the input that triggers the worst case.

3. Explain why choosing the pivot at random makes the bad case vanishingly unlikely.

4. Solve the selection problem, finding the k-th smallest item, with quickselect, without sorting the whole list.

5. Describe the median-of-medians pivot rule and explain why it guarantees fast selection even in the worst case.

2. What survived from Merge Sort & the Master Theorem?

Warm-up

Discussion prompt

Before we open Quicksort, Selection & Median of Medians: without looking back, what was the main idea of Merge Sort & the Master Theorem, and what could you do by the end of it that you could not do before?

Hint: One sentence for the idea, one for the skill. If the second one is blank, that is the part to revisit.

Answer:

That deck traces merge sort end to end, explains why the merge step is linear, sets up the merge sort recurrence, and works the Master Theorem's three cases by comparing the extra work f(n) against the watershed function n^log_b(a). It targets swapping a and b, mis-comparing f(n) to the watershed, assuming the merge step is free, and force-fitting recurrences - those with log-factor gaps or unequal splits - that do not satisfy the theorem's hypotheses.

3. Toolkit check-in: name them before you look

Concept

Before any new material: cover the screen.

You have named 11 reusable moves so far. Say as many as you can out loud, by number, from memory.

Do not advance until you have actually tried. Getting four of eight is information; skipping the exercise is not.

Here they are. Score yourself.

Today adds no new moves. Every proof in this lesson is built out of the list above. That is the whole point of the list.

The question that starts every proof from here on is not how do I begin. It is which of these applies here?

4. Break it if you can: Toolkit check-in: name them before you look

Counterexample

Discussion prompt

You have named 11 reusable moves so far. Say as many as you can out loud, by number, from memory.

That is stated as though it always holds. Do one of two things: produce a case where it fails, or say precisely what rules such a case out. "It just does" is not on the menu.

Hint: Hunt at the extremes first — zero, one, negative, empty, equal. If every extreme survives, the reason they survive is the proof.

Answer:

Do not advance until you have actually tried. Getting four of eight is information; skipping the exercise is not.

5. Quicksort in one sentence

Concept

Quicksort sorts a list by picking one item to act as a pivot, rearranging the list so everything smaller comes before it and everything bigger comes after it, then sorting each of those two pieces the same way.

That rearranging step is called partitioning. Once a list is partitioned around a pivot, the pivot itself never needs to move again, only the two pieces on either side still need sorting.

6. Partition around a pivot

Picture it

Animation

Shows: Partition around a pivot — a rendered Manim animation.

Rendered with Manim.

Takeaway: One pass, and the pivot never moves again.

7. Splitting one pile into two

Intuition

Picture a messy pile of exam papers. You grab one paper at random, call it the pivot, and sort every other paper into a smaller pile or a bigger pile compared to it.

The pivot paper is now exactly where it belongs, nothing smaller is after it, nothing bigger is before it. You repeat the same trick on each of the two smaller piles, and keep going until every pile has just one paper left.

8. By analogy: Splitting one pile into two

Analogy

Discussion prompt

Explain Splitting one pile into two by analogy to something with no CS3000 Algorithms in it at all — a queue, a recipe, a map, a bank balance, whatever fits. Then say where your analogy breaks.

Hint: An analogy that never breaks is not an analogy, it is the same idea wearing a hat. Find the seam — that is the part that is actually new.

Answer:

Picture a messy pile of exam papers. You grab one paper at random, call it the pivot, and sort every other paper into a smaller pile or a bigger pile compared to it.

9. What it means for a list to be "partitioned"

Concept

pivot — The one item chosen to compare every other item against during a partition step. After partitioning, the pivot sits in its final sorted position.

partition — Rearranging a list around a chosen pivot so every item before the pivot is less than or equal to it, and every item after the pivot is greater than or equal to it.

Partitioning does not sort either side, it only guarantees the split is in the right order relative to the pivot. Each side still needs its own sorting pass.

10. Teach it back: What it means for a list to be "partitioned"

Explain it

Discussion prompt

Explain What it means for a list to be "partitioned" to a student a year behind you. No notation, no jargon they have not met — and it still has to be true.

Hint: If your explanation needs a symbol they have never seen, you are describing the notation rather than the idea.

Answer:

Partitioning does not sort either side, it only guarantees the split is in the right order relative to the pivot. Each side still needs its own sorting pass.

11. How the partition scan works

Concept

Pick the pivot (a common choice: the last item in the range). Then walk through every other item once, left to right.

Keep a boundary marking how many items so far belong in the smaller-or-equal group. Whenever the current item is smaller than or equal to the pivot, swap it just past that boundary and move the boundary forward.

After the single pass, swap the pivot into the spot right after the boundary. Everything before it is smaller-or-equal, everything after it is bigger. One pass through the list is all a single partition costs.

12. Partition in pseudocode

Concept

Partition is the engine of both quicksort and quickselect, and it is one loop. A boundary marches through the array, and everything behind it is known to be small.

PARTITION(A, lo, hi)
  pivot = A[hi]
  b = lo - 1
  for j = lo to hi - 1
    if A[j] <= pivot
      b = b + 1
      swap A[b] with A[j]
  swap A[b + 1] with A[hi]
  return b + 1

The variable b is a boundary, not a counter. Everything from lo to b is at most the pivot, and everything from b plus one to j minus one is greater. Line 8 finally drops the pivot into the gap between them.

13. Reading PARTITION line by line

Notation

Every line of PARTITION says one thing. Read the line, then read what it does — not the other way round.

Annotate

  • The last element is the pivot, by convention. Any choice works; this one just makes the indices tidy.
  • The boundary starts before the array, meaning the small region is empty. Off-by-one errors here are the classic partition bug.
  • The scan stops one short of hi, because the pivot itself is sitting there and must not be moved yet.
  • Found something small: grow the small region by one, and swap the newcomer into the slot that just opened up.
  • The pivot takes its final position, between the two regions. It never moves again for the rest of the sort.
  • Return where the pivot landed. Quicksort recurses on both sides of this index; quickselect recurses on only one.

14. Step PARTITION yourself

Invariant

Everything left of the boundary is at most the pivot, and everything between the boundary and the scanner is greater. Both statements stay true after every single pass of the loop.

Step through it

At each step, say which region the scanner's current item is about to join.

  1. Line 2: the pivot is 6
  2. Line 5: 7 is bigger, so leave it
  3. Line 5: 2 is smaller
  4. Line 7: swap it behind the boundary
  5. Line 5: 9 is bigger, leave it
  6. Line 5: 4 is smaller
  7. Line 7: swap it in
  8. Line 8: the pivot drops into the gap
  9. Line 9: 6 is now in its final place forever

15. One pass, one boundary, the pivot lands home

Picture it

Animation

Shows: PARTITION executing: the current line of pseudocode is highlighted while the data it touches changes.

Rendered with Manim.

Takeaway: One left-to-right pass and a moving boundary put the pivot in its final place — linear time, and no extra array.

16. Partitioning happens in place

Concept

Quicksort's partition step only swaps items within the original list. It never copies the list into new, separate arrays the way some other sorting methods do.

That is one reason quicksort is popular in practice: it sorts using very little extra memory beyond the list itself, even though it uses more memory behind the scenes for the recursive calls.

17. Picture it first: Worked example: partition one array by hand

Picture it

Figure (svg): Seven boxes in a row holding the numbers 8, 3, 7, 4, 9, 2, 5, with the last box labeled as the pivot

Discussion prompt

Read the picture before the words. What is this showing, and what is the one thing it is built to make obvious? Commit to an answer, then read on.

Hint: Name the parts, then say what changes between them — and if nothing changes, say what is being held still.

Answer:

Partition the list 8, 3, 7, 4, 9, 2, 5 using the last item, 5, as the pivot.

18. Worked example: partition one array by hand

Worked example

Partition the list 8, 3, 7, 4, 9, 2, 5 using the last item, 5, as the pivot.

Figure (svg): Seven boxes in a row holding the numbers 8, 3, 7, 4, 9, 2, 5, with the last box labeled as the pivot

Scan left to right, comparing each item to the pivot (5)

Why: 8 is greater than 5, so it stays put for now, nothing to swap yet.

3 is less than or equal to 5, so swap it into the boundary spot

Why: 3 belongs in the smaller-or-equal group. Swapping 8 and 3 gives 3, 8, 7, 4, 9, 2, 5 and moves the boundary forward by one.

7 is greater than 5, so it stays; 4 is less than or equal to 5, so swap it in

Why: Swapping 8 and 4 gives 3, 4, 7, 8, 9, 2, 5, moving the boundary forward again.

9 is greater than 5, so it stays; 2 is less than or equal to 5, so swap it in

Why: Swapping 7 and 2 gives 3, 4, 2, 8, 9, 7, 5, moving the boundary forward one more time.

Swap the pivot into the spot right after the boundary

Why: Swapping 5 with 8 gives the final partitioned list: 3, 4, 2, 5, 9, 7, 8. The pivot 5 now sits exactly where it belongs.

item scannedcompared to pivot 5list after this step
8greater, skip8, 3, 7, 4, 9, 2, 5
3less or equal, swap in3, 8, 7, 4, 9, 2, 5
7greater, skip3, 8, 7, 4, 9, 2, 5
4less or equal, swap in3, 4, 7, 8, 9, 2, 5
9greater, skip3, 4, 7, 8, 9, 2, 5
2less or equal, swap in3, 4, 2, 8, 9, 7, 5
pivot 5swap into final spot3, 4, 2, 5, 9, 7, 8

Verify the partition is correct

Why: Everything before the pivot (3, 4, 2) is less than or equal to 5, and everything after it (9, 7, 8) is greater than or equal to 5. The pivot sits at its final sorted position.

19. Fill in: compared to pivot 5 for Worked example: partition one array by hand

Comparison

Comparison matrix

From Worked example: partition one array by hand: refill the compared to pivot 5 column from what you know. The rest of the table is as it appeared.

item scannedcompared to pivot 5list after this step
8greater, skip8, 3, 7, 4, 9, 2, 5
3less or equal, swap in3, 8, 7, 4, 9, 2, 5
7greater, skip3, 8, 7, 4, 9, 2, 5
4less or equal, swap in3, 4, 7, 8, 9, 2, 5
9greater, skip3, 4, 7, 8, 9, 2, 5
2less or equal, swap in3, 4, 2, 8, 9, 7, 5
pivot 5swap into final spot3, 4, 2, 5, 9, 7, 8

20. Quicksort recurses on both sides of the pivot

Concept

Once a partition places the pivot correctly, quicksort calls itself on the piece before the pivot and, separately, on the piece after it.

The pivot itself is left alone from here on, it already sits in its final position. Each recursive call partitions its own smaller piece the same way, choosing a new pivot from within that piece.

21. Why the recursion always bottoms out

Intuition

Every partition places one item, the pivot, into its final spot and hands off two strictly smaller pieces to sort. The pieces can never be as big as the piece that produced them.

Eventually a piece has zero or one items left. A piece that small is already sorted by definition, so the recursion simply stops there, no further pivoting is needed.

22. What has to happen first: Worked example: quicksort start to finish

Ranking

Put in order

Put the moves of Worked example: quicksort start to finish into the order they have to happen.

  1. First partition (shown earlier) splits the whole list
  2. Partition the left piece, 3, 4, 2, around pivot 2
  3. Partition 4, 3 around pivot 3
  4. Partition the right piece, 9, 7, 8, around pivot 8
  5. Every piece is now down to zero or one items, so stitch the results back together in order
  6. Verify the final order is fully sorted

Why: These are the moves of the worked example in the order it makes them, and each one is set up by the one before it. Around pivot 5, the list becomes the piece 3, 4, 2, then 5, then the piece 9, 7, 8.

23. Worked example: quicksort start to finish

Worked example

Continue sorting 8, 3, 7, 4, 9, 2, 5 using the last item of each piece as its pivot.

First partition (shown earlier) splits the whole list

Why: Around pivot 5, the list becomes the piece 3, 4, 2, then 5, then the piece 9, 7, 8.

Partition the left piece, 3, 4, 2, around pivot 2

Why: 2 is smaller than both 3 and 4, so it ends up first: the piece becomes 2, then the remaining piece 4, 3.

Partition 4, 3 around pivot 3

Why: 3 is smaller than 4, so they swap to 3, 4, pivot 3 is first, leaving the single-item piece 4.

callpiece being sortedpivot usedresult
18, 3, 7, 4, 9, 2, 55(3, 4, 2), 5, (9, 7, 8)
23, 4, 22(), 2, (4, 3)
34, 33(), 3, (4)
49, 7, 88(7), 8, (9)

Partition the right piece, 9, 7, 8, around pivot 8

Why: 7 is smaller than 8 and swaps forward; 9 stays put. The piece becomes 7, then 8, then the single-item piece 9.

Every piece is now down to zero or one items, so stitch the results back together in order

Why: Reading left to right: 2, then 3, then 4, then the original pivot 5, then 7, then 8, then 9.

\[ 2,\ 3,\ 4,\ 5,\ 7,\ 8,\ 9 \]

Verify the final order is fully sorted

Why: The original items were 8, 3, 7, 4, 9, 2, 5, the same seven values, now listed from smallest to largest with none missing or repeated.

24. Randomisation removes the bad input

Picture it

Animation

Shows: Randomisation removes the bad input — a rendered Manim animation.

Rendered with Manim.

Takeaway: No adversary can pick an input that is reliably bad.

25. The running time depends on how balanced each split is

Concept

Every partition costs one pass through the current piece, proportional to that piece's size. What changes from case to case is how many more partitions are still needed afterward.

If a pivot splits its piece into two roughly equal halves, the two recursive calls attack much smaller pieces. If a pivot splits its piece into one tiny piece and one almost-as-big piece, barely any progress was made.

26. The Split-Quality skeleton

Concept

Every proof of this kind has the same five or six moves in the same order. The order is not something you rediscover each time.

It is on the right. It will stay on the right through the worked examples that follow.

Why this matters: the structure is now handled. You are not spending working memory on what comes next — you are spending all of it on the one hard step.

Step 4 is the one people skip. A running time that is only true for friendly inputs is not a running time — worst case means an adversary picks the input after seeing your code.

27. Picture the recursion as a tree of shrinking pieces

Intuition

Draw one box for the original list, then two boxes underneath for the two pieces its first partition produces, then boxes underneath those for their pieces, and so on.

If every split is close to even, the boxes shrink toward size one quickly, the tree is short and wide. If a split keeps peeling off just one item at a time, the tree is tall and thin, with barely any shrinking per level.

28. Best case: perfectly balanced splits

Concept

If every pivot happens to land exactly in the middle of its piece, each level of the recursion tree does a total amount of work proportional to the size of the whole original list.

\[ T(n) = 2\,T\!\left(\frac{n}{2}\right) + \Theta(n) \]

A list of size n can only be cut in half so many times before reaching size one, about that many levels exist. Multiplying the per-level cost by the number of levels gives the best-case running time.

\[ T(n) = \Theta(n \log n) \]

29. Plan first: Worked example: checking the n log n shape for n = 8

Step zero

Discussion prompt

Worked example: checking the n log n shape for n = 8 — before any calculation: what is the plan? Name the moves in order, in plain English, without doing the arithmetic.

Hint: It starts with: Count how many times 8 can be halved before reaching size 1

Answer:

  1. Count how many times 8 can be halved before reaching size 1
  2. Add up the partitioning cost at each level
  3. Verify the total matches the n log n shape

30. Worked example: checking the n log n shape for n = 8

Worked example

Suppose a list of 8 items always splits into two even halves.

Count how many times 8 can be halved before reaching size 1

Why: 8, 4, 2, 1, that is 3 halvings, so the recursion tree has 3 levels below the top, or about log base 2 of 8 levels.

\[ \log_{2}(8) = 3 \]

Add up the partitioning cost at each level

Why: The top level partitions 8 items, the next level partitions two pieces of 4 (still 8 items total), the next partitions four pieces of 2 (still 8 items total). Each level costs about 8.

levelpiecestotal items partitioned
01 piece of size 88
12 pieces of size 48
24 pieces of size 28

Verify the total matches the n log n shape

Why: Three levels at a cost of about 8 each gives roughly 8 times 3, which is 24, the same shape as n times log base 2 of n for n equal to 8, since log base 2 of 8 is 3.

\[ 8 \times \log_{2}(8) = 8 \times 3 = 24 \]

31. checking the n log n shape for n = 8 — line by line

Picture it

Animation

Shows: Each line of the worked example "checking the n log n shape for n = 8", appearing one at a time.

The same working the example does, in the order a tutor would write it.

Takeaway: Three levels at a cost of about 8 each gives roughly 8 times 3, which is 24, the same shape as n times log base 2 of n for n equal to 8, since log base 2 of 8 is 3.

32. Worst case: maximally unbalanced splits

Concept

If every pivot happens to be the smallest or the largest item in its piece, one side of the partition is empty and the other side has everything else.

\[ T(n) = T(n-1) + \Theta(n) \]

Now barely any progress is made per partition, the piece only shrinks by one item at a time. Adding up the shrinking costs gives a running time that grows with the square of the list's size.

\[ T(n) = \Theta(n^{2}) \]

33. What input actually forces the worst case

Intuition

The worst case is not about bad luck in general, it happens whenever the pivot rule keeps picking an extreme item on purpose.

The classic trigger: a list that is already sorted (or reverse sorted), combined with a pivot rule that always picks the first (or last) item. On sorted input, the first item is always the smallest of whatever is left, so every partition peels off exactly one item.

34. Decision point: we claim quicksort is n log n. Attack it.

Intuition

What move should we make next?

The claim on the table:

\[ \text{quicksort runs in } \Theta(n \log n) \]

You are now the adversary. You get to choose the array after seeing that the pivot is always the first element.

This is a for-all claim about every input. Which move do you reach for, and what would you build?

_Look at your toolkit. Say a move number out loud before this slide advances._ A wrong guess is useful. A silent guess is not.

35. Two partition schemes

Picture it

Animation

Shows: Two partition schemes — a rendered Manim animation.

Rendered with Manim.

Takeaway: Same asymptotics, noticeably different constants.

36. Guess the shape of the answer: Worked example: naive pivot on…

Estimation

Predict first

Sort the already-sorted list 1, 2, 3, 4, 5 using a pivot rule that always picks the first item of the current piece.

Commit before you compute: what does Worked example: naive pivot on already-sorted input come out to? A rough magnitude and the right form is enough — the point is to have something concrete to be wrong about.

Correct: Verify this matches the quadratic worst-case formula

Why: A prediction you can defend turns the computation into a check rather than a leap of faith — and an answer that contradicts it is caught on the spot. The general worst-case comparison count is n times (n minus 1), divided by 2.

37. Worked example: naive pivot on already-sorted input

Worked example

Sort the already-sorted list 1, 2, 3, 4, 5 using a pivot rule that always picks the first item of the current piece.

Partition 1, 2, 3, 4, 5 around pivot 1

Why: 1 is the smallest item, so every one of the other four items lands on its greater side. The piece becomes 1, then the piece 2, 3, 4, 5, no items removed except the pivot.

piece sizepivotcomparisons maderemaining piece size
5144
4233
3322
2411
1500

Repeat on each remaining piece: 2,3,4,5 then 3,4,5 then 4,5 then 5

Why: Each partition again picks the smallest item as the first element, again peeling off exactly one item and comparing against every item still left.

Add the comparisons made at every step

Why: 4 plus 3 plus 2 plus 1 plus 0 is 10 total comparisons for these 5 items.

\[ 4+3+2+1+0 = 10 \]

Verify this matches the quadratic worst-case formula

Why: The general worst-case comparison count is n times (n minus 1), divided by 2. For n equal to 5, that is 5 times 4 divided by 2, which is also 10, matching the direct count.

\[ \frac{n(n-1)}{2} = \frac{5 \times 4}{2} = 10 \]

38. naive pivot on already-sorted input — line by line

Picture it

Animation

Shows: Each line of the worked example "naive pivot on already-sorted input", appearing one at a time.

The same working the example does, in the order a tutor would write it.

Takeaway: The general worst-case comparison count is n times (n minus 1), divided by 2. For n equal to 5, that is 5 times 4 divided by 2, which is also 10, matching the direct count.

39. What has to be given first: Worked example: a better pivot on the same…

Missing information

Discussion prompt

Sort the same list, 1, 2, 3, 4, 5, but this time choose the middle item, 3, as the pivot instead of the first item.

What do you need to know — or decide — before the first line can be written? List everything the problem has to hand you.

Hint: Anything you would have to invent to get started is a thing the problem must supply.

Answer:

Items 1 and 2 are less than 3; items 4 and 5 are greater than 3. The piece splits into 1, 2 on one side and 4, 5 on the other, both size 2.

40. Worked example: a better pivot on the same sorted list

Worked example

Sort the same list, 1, 2, 3, 4, 5, but this time choose the middle item, 3, as the pivot instead of the first item.

Partition 1, 2, 3, 4, 5 around pivot 3

Why: Items 1 and 2 are less than 3; items 4 and 5 are greater than 3. The piece splits into 1, 2 on one side and 4, 5 on the other, both size 2.

sideitemssize
smaller than pivot1, 22
pivot31
greater than pivot4, 52

Compare this split to the naive pivot's split

Why: The naive first-element pivot produced pieces of size 0 and 4 from this same list. Choosing the middle item instead produced pieces of size 2 and 2, a much more even split from the exact same starting list.

Verify the same input can behave very differently depending on the pivot

Why: Nothing about the list 1, 2, 3, 4, 5 changed between the two examples, only the rule for picking the pivot changed, and that alone flipped the split from maximally unbalanced to perfectly balanced.

41. a better pivot on the same sorted list — line by line

Picture it

Animation

Shows: Each line of the worked example "a better pivot on the same sorted list", appearing one at a time.

The same working the example does, in the order a tutor would write it.

Takeaway: Nothing about the list 1, 2, 3, 4, 5 changed between the two examples, only the rule for picking the pivot changed, and that alone flipped the split from maximally unbalanced to perfectly balanced.

42. Something is wrong here: "quicksort is always n log n"

Anomaly

Predict first

A student writes this, and it looks reasonable:

A student remembers that quicksort is one of the fast sorting algorithms and assumes its running time is always proportional to n log n, no matter the input or the pivot rule.

It is wrong. Say what breaks — and say it before you turn the page.

Correct: This is exactly the setup from the worked example a few slides back: every partition only removes one item, and the student's assumed running time is simply wrong for this case.

n log n describes the best case and, with a good pivot rule, the average case, it is not a guarantee for every combination of input and pivot rule.

Why: This is exactly the setup from the worked example a few slides back: every partition only removes one item, and the student's assumed running time is simply wrong for this case.

43. Trap: "quicksort is always n log n"

Trap

The trap

A student remembers that quicksort is one of the fast sorting algorithms and assumes its running time is always proportional to n log n, no matter the input or the pivot rule.

\[ \text{Claimed always: } T(n) = \Theta(n \log n) \]

Apply that assumption to a sorted list with a first-element pivot

Why: This is exactly the setup from the worked example a few slides back: every partition only removes one item, and the student's assumed running time is simply wrong for this case.

\[ \text{Actual: } T(n) = \Theta(n^{2})\ \text{on this input} \]

The fix

n log n describes the best case and, with a good pivot rule, the average case, it is not a guarantee for every combination of input and pivot rule.

\[ \text{Best/average case: } \Theta(n \log n) \]

Name the pivot rule and the input before naming the running time

Why: A sorted list with a first-or-last-element pivot rule genuinely does run in quadratic time. Whether n log n applies depends on that combination, not on quicksort's name alone.

\[ \text{Worst case: } \Theta(n^{2}),\ \text{triggered by sorted input} + \text{naive pivot} \]

44. Decode the notation: Trap: "quicksort is always n log n"

Notation

Annotate

From Trap: "quicksort is always n log n" — read this one piece at a time. What is each part doing?

On: \( \text{Claimed always: } T(n) = \Theta(n \log n) \)

  • This is exactly the setup from the worked example a few slides back: every partition only removes one item, and the student's assumed running time is simply wrong for this case.
  • A sorted list with a first-or-last-element pivot rule genuinely does run in quadratic time. Whether n log n applies depends on that combination, not on quicksort's name alone.

45. What feels wrong about these two facts together?

Intuition

What feels wrong about this?

Both of these are true about the same algorithm:

\[ \text{worst case: } \Theta(n^{2}), \qquad \text{average case: } \Theta(n \log n) \]

_Plain English only. No notation, no algebra. Just say what bothers you._

The feeling: if the worst case is quadratic, it feels like the average should be dragged somewhere in between — not sitting right down at the good end.

That feeling is the proof. It is not a substitute for the proof — it is the thing the proof writes down.

The resolution is counting: quadratic behaviour needs a badly unbalanced split at nearly every level, and the overwhelming majority of pivot choices are not that bad. Rare disasters barely move an average.

46. Average case: also n log n

Concept

For a random pivot on a typical (not adversarially chosen) list, the split is usually somewhere in the middle range, not perfectly even, but not maximally lopsided either.

Averaging over all the possible pivot positions, the expected running time works out to the same n log n shape as the best case, just with a somewhat larger constant factor.

\[ \mathbb{E}[T(n)] = \Theta(n \log n) \]

47. Why the average is n log n

Picture it

Animation

Shows: Why the average is n log n — a rendered Manim animation.

Rendered with Manim.

Takeaway: The split need not be even — only not catastrophic.

48. Why the average case isn't close to the worst case

Intuition

The worst case needs the pivot to land on an extreme item, the very smallest or very largest, over and over, every single time. Most positions in a piece are not extreme.

Even a so-so split, say one third and two thirds, still removes a real chunk of the piece each time. Only a long, unlucky streak of extreme splits reproduces the quadratic behavior, and that streak is what a fixed, sorted-input-exploiting pivot rule guarantees, not what typical data produces.

49. Randomized pivot selection

Concept

Instead of always picking the first or last item, pick the pivot uniformly at random from the current piece, using a fresh random choice at every single partition call.

This is called randomized quicksort. The algorithm's steps are otherwise identical, only where the pivot comes from has changed.

50. The pivot decides everything

Picture it

Animation

Shows: The pivot decides everything — a rendered Manim animation.

Rendered with Manim.

Takeaway: Already-sorted input with a first-element pivot hits the worst case.

51. Randomization takes the input out of the driver's seat

Intuition

With a fixed pivot rule, like always picking the first item, some specific input (a sorted list) can be built ahead of time to trigger the worst case every single partition.

With a random pivot, no fixed input can do that, because the pivot itself is not determined by the input at all, it depends on a coin flip made fresh each call. A sorted list is no more dangerous than any other list once the pivot is chosen randomly.

52. Plan first: Worked example: what a random pivot buys you

Step zero

Discussion prompt

Worked example: what a random pivot buys you — before any calculation: what is the plan? Name the moves in order, in plain English, without doing the arithmetic.

Hint: It starts with: Find the chance a uniformly random pivot is good

Answer:

  1. Find the chance a uniformly random pivot is good
  2. Work out what a good pivot guarantees
  3. Verify that repeated good pivots keep the recursion short

53. Worked example: what a random pivot buys you

Worked example

Call a pivot "good" if it lands somewhere in the middle half of the current piece, not among the smallest quarter or the largest quarter.

Find the chance a uniformly random pivot is good

Why: The middle half of the piece is, by definition, half of all the positions a random pivot could land on.

\[ P(\text{good pivot}) = \frac{1}{2} \]

Work out what a good pivot guarantees

Why: A pivot in the middle half always leaves the larger side with at most three quarters of the piece, never the near-total pieces a worst-case pivot leaves behind.

\[ \text{good pivot} \Rightarrow \text{larger side} \le \frac{3n}{4} \]

Verify that repeated good pivots keep the recursion short

Why: Shrinking a piece by a factor of three quarters, over and over, still only takes about a logarithmic number of shrinks to reach size one, and a random pivot lands "good" about every other try, on average, so the expected depth stays logarithmic even with some unlucky draws mixed in.

54. what a random pivot buys you — line by line

Picture it

Animation

Shows: Each line of the worked example "what a random pivot buys you", appearing one at a time.

The same working the example does, in the order a tutor would write it.

Takeaway: Shrinking a piece by a factor of three quarters, over and over, still only takes about a logarithmic number of shrinks to reach size one, and a random pivot lands "good" about every other try, on average, so the expected depth stays logarithmic even with some unlucky draws mixed in.

55. Something is wrong here: "pivot choice doesn't matter for the worst case"

Anomaly

Predict first

A student writes this, and it looks reasonable:

A student argues that since the worst case is technically still possible for a randomized pivot, some unlucky run of coin flips could always pick an extreme item every time, randomization doesn't actually change anything.

It is wrong. Say what breaks — and say it before you turn the page.

Correct: This mixes up "possible" with "likely." The worst case being reachable in principle says nothing about how often it actually happens, and that gap is exactly the point of randomizing.

Pivot choice controls whether the worst case is something an adversary can force, or something so improbable it essentially never shows up.

Why: This mixes up "possible" with "likely." The worst case being reachable in principle says nothing about how often it actually happens, and that gap is exactly the point of randomizing.

56. Trap: "pivot choice doesn't matter for the worst case"

Trap

The trap

A student argues that since the worst case is technically still possible for a randomized pivot, some unlucky run of coin flips could always pick an extreme item every time, randomization doesn't actually change anything.

\[ \text{Worst case still exists: } \Theta(n^{2})\ \text{(technically possible)} \]

Conclude that pivot choice is irrelevant to performance

Why: This mixes up "possible" with "likely." The worst case being reachable in principle says nothing about how often it actually happens, and that gap is exactly the point of randomizing.

The fix

Pivot choice controls whether the worst case is something an adversary can force, or something so improbable it essentially never shows up.

\[ \text{Fixed pivot on chosen input: worst case is guaranteed} \]

Compare the two pivot rules on the exact same input

Why: A fixed first-element pivot on a sorted list hits the quadratic worst case every single time. A random pivot on that same sorted list has an expected running time of n log n, because good splits happen often enough regardless of how the input was arranged.

\[ \text{Random pivot on any fixed input: } \mathbb{E}[T(n)] = \Theta(n \log n) \]

57. Say it in words: Trap: "pivot choice doesn't matter for the worst…

Translation

\( \text{Random pivot on any fixed input: } \mathbb{E}[T(n)] = \Theta(n \log n) \)

Draw it

Translate both ways. First write the expression above as a sentence with no symbols in it at all. Then cover it, and write your sentence back as notation. If the two versions disagree, the disagreement is the thing to fix.

58. How to reason about quicksort's running time

Pattern

1. Ask how balanced the split is

Why: The running time is entirely a story about split balance, perfectly even splits, wildly uneven splits, and everything in between.

2. Perfectly balanced splits give n log n; maximally unbalanced splits give quadratic

Why: These are the two extremes: even splitting shrinks the piece geometrically every level; one-at-a-time splitting barely shrinks it at all.

3. Name the pivot rule and the input together before claiming a running time

Why: Quicksort alone does not determine performance, a fixed pivot rule paired with an input built to exploit it produces the worst case; a random pivot paired with any input produces expected n log n.

4. Randomizing the pivot trades a guaranteed bad case for an astronomically unlikely one

Why: No input can force randomized quicksort into its worst case on purpose, because the pivot no longer depends on the input at all.

59. Where this shows up: Quicksort, Selection & Median of Medians

Real world

Discussion prompt

Outside this lesson: where does Quicksort, Selection & Median of Medians actually turn up? Name one concrete situation — a job, a piece of software someone ships, a decision somebody has to make — and say which part of How to reason about quicksort's running time is doing the work in it.

Hint: Vague is the failure mode here. "Engineering" is not a situation; "deciding whether this build is fast enough to ship" is.

Answer:

That deck covers quicksort's partition step and its recursion, the best, average, and worst-case running times, and the sorted input that triggers the worst case. It then explains randomized pivots and why they make the bad case vanishingly unlikely, introduces the selection problem and quickselect, and gives the median-of-medians pivot rule, using groups of five, that guarantees linear worst-case selection. It targets the myths that quicksort is always n log n, that selection requires a full sort, and that the choice of pivot does not matter for the worst case, and it explains why groups of five in particular are used.

60. Many duplicates break naive partition

Picture it

Animation

Shows: Many duplicates break naive partition — a rendered Manim animation.

Rendered with Manim.

Takeaway: Three-way partitioning fixes this by grouping equals in the middle.

61. Rule out three: Check yourself: naive pivot on sorted input

Elimination

Eliminate the wrong options

What is the running time of this sort, and why?

3 of these 4 are wrong. Strike them one at a time, and say what rules each one out before you strike the next. The survivor is the answer.

  • A. Quadratic, because every partition only removes the pivot and leaves the other 999 (then 998, then 997, ...) items in one big piece.
  • B. n log n, because quicksort always runs at this speed regardless of the pivot rule or the input.
  • C. Linear, because the list is already sorted so no items ever need to be swapped.
  • D. Logarithmic, because a sorted list can be searched in log time.

Survives elimination: A

Why: On sorted input, the first item of any piece is always its smallest item. Picking it as the pivot means every partition peels off exactly one item, leaving a piece one smaller than before, giving the classic quadratic worst-case pattern of n, n minus 1, n minus 2, and so on.

62. Check yourself: naive pivot on sorted input

Check

A list of 1,000 already-sorted numbers is quicksorted using a pivot rule that always picks the first item of the current piece.

Check your understanding

What is the running time of this sort, and why?

  • A. Quadratic, because every partition only removes the pivot and leaves the other 999 (then 998, then 997, ...) items in one big piece. (correct)
  • B. n log n, because quicksort always runs at this speed regardless of the pivot rule or the input.
  • C. Linear, because the list is already sorted so no items ever need to be swapped.
  • D. Logarithmic, because a sorted list can be searched in log time.

Answer: A

Why: On sorted input, the first item of any piece is always its smallest item. Picking it as the pivot means every partition peels off exactly one item, leaving a piece one smaller than before, giving the classic quadratic worst-case pattern of n, n minus 1, n minus 2, and so on.

Why B tempts people
This is the exact myth this lesson targets: quicksort's speed depends on the pivot rule and the input together, and this specific combination is the textbook trigger for the worst case, not the best case.
Why C tempts people
Being pre-sorted does not eliminate comparisons, the algorithm still has to compare every item to the pivot to decide which side it belongs on, even if the answer never causes a swap.
Why D tempts people
Logarithmic time describes searching a sorted list for one item, not rearranging (or in this case, re-confirming the order of) every item in it. Sorting always touches every element at least once.

63. The selection problem: finding the k-th smallest

Concept

Sometimes you don't need a whole list in order, you just need to know one specific rank, like the smallest item, the largest, or the middle (median) one.

This is the selection problem: given a list and a target rank k, find the item that would sit in position k if the list were fully sorted.

64. You only need one rank, not the whole order

Intuition

Think of finding the median test score in a class. You don't care which student scored 2nd or 15th, you only care about the one score sitting in the middle position.

Fully sorting the whole class list would answer that question, but it would also answer a hundred questions nobody asked. Selection aims to answer only the one question that was actually asked.

65. Something is wrong here: confusing selection with full sorting

Anomaly

Predict first

A student writes this, and it looks reasonable:

A student needs the 5th smallest item out of 1,000 unsorted numbers. Their plan: sort the whole list first, then read off the item in position 5.

It is wrong. Say what breaks — and say it before you turn the page.

Correct: Fully sorting costs an n log n amount of work to determine the order of every single item, when only one specific rank was ever asked for.

Selection never needs the full order, only enough partitioning to isolate the one target rank.

Why: Fully sorting costs an n log n amount of work to determine the order of every single item, when only one specific rank was ever asked for.

66. Trap: confusing selection with full sorting

Trap

The trap

A student needs the 5th smallest item out of 1,000 unsorted numbers. Their plan: sort the whole list first, then read off the item in position 5.

This works, but it does far more work than the question requires.

Sort all 1,000 items to answer a question about just one of them

Why: Fully sorting costs an n log n amount of work to determine the order of every single item, when only one specific rank was ever asked for.

The fix

Selection never needs the full order, only enough partitioning to isolate the one target rank.

Quickselect (covered next) answers exactly this kind of question directly, without fully sorting.

Partition around a pivot and recurse into only the piece containing the target rank

Why: The moment a partition tells you which side the target rank lands on, the other side can be thrown away entirely, its internal order was never asked for.

67. Break it on purpose: confusing selection with full sorting

Break the constraint

Discussion prompt

The rule this trap just fixed:

The moment a partition tells you which side the target rank lands on, the other side can be thrown away entirely, its internal order was never asked for.

Now break it on purpose. Build a case that violates it and follow the consequences until something visibly fails. Where does the failure first show up — and would you have noticed it if you had not been looking?

Hint: The dangerous rules are the ones whose violation still produces an answer. If yours fails loudly, try to find one that fails quietly.

Answer:

Fully sorting costs an n log n amount of work to determine the order of every single item, when only one specific rank was ever asked for.

68. Quickselect: partition once, recurse into one side

Concept

Quickselect finds the k-th smallest item using the same partition step as quicksort, but after each partition it looks at where the pivot landed compared to the target rank k.

If the pivot's position is exactly k, the pivot is the answer, done. If the pivot's position is past k, the answer must be somewhere in the smaller-side piece, so recurse only there. If the pivot's position is before k, recurse only into the bigger-side piece, adjusting k to account for the items already ruled out.

69. Quickselect in pseudocode

Concept

Quickselect is quicksort with one line deleted. Because it only wants one item, it can throw away the side that cannot contain it instead of sorting both.

QUICKSELECT(A, lo, hi, k)
  if lo == hi
    return A[lo]
  p = PARTITION(A, lo, hi)
  if k == p
    return A[p]
  else if k < p
    return QUICKSELECT(A, lo, p - 1, k)
  else
    return QUICKSELECT(A, p + 1, hi, k)

Compare this with quicksort, which recurses on lines 8 and 10 both. Quickselect picks exactly one of them. Two calls give n log n; one call gives linear time on average, because the work halves each round instead of doubling.

70. Reading QUICKSELECT line by line

Notation

Every line of QUICKSELECT says one thing. Read the line, then read what it does — not the other way round.

Annotate

  • The same PARTITION, unchanged. Everything quickselect saves comes from what it does with the answer, not from partitioning differently.
  • If the pivot landed exactly on the rank you wanted, you are done — no recursion at all.
  • The target rank is left of the pivot, so the whole right side is discarded, pivot included.
  • The mirror case. Note that k is not adjusted here because ranks are absolute indices, not offsets.
  • One call, not two. That single difference is the entire gap between linear and n log n.

71. Step QUICKSELECT yourself

Invariant

The live range only ever shrinks, and the item of rank k is always inside it. When the range narrows to one item, that item is the answer.

Step through it

At each recursion, say which half is being thrown away and why it cannot hold the answer.

  1. Line 1: find the item of rank 2
  2. Line 4: partition puts 6 at index 2
  3. Line 7: rank 2 is less than index 2? no, equal
  4. Line 5: the pivot IS the answer
  5. Line 6: return without recursing at all
  6. Line 8: had rank been 0 or 1, only this side would survive
  7. Line 10: and had it been 3 or 4, only this one

72. Throw away the side that cannot hold the answer

Picture it

Animation

Shows: QUICKSELECT executing: the current line of pseudocode is highlighted while the data it touches changes.

Rendered with Manim.

Takeaway: Partition, then recurse into one side only — the discarded half is why quickselect averages linear time instead of n log n.

73. Quickselect: recurse into one side only

Picture it

Animation

Shows: Quickselect: recurse into one side only — a rendered Manim animation.

Rendered with Manim.

Takeaway: Discarding one side collapses the log factor entirely.

74. Quickselect throws away the side that can't hold the answer

Intuition

Quicksort keeps both pieces after a partition because it eventually needs everything in order. Quickselect only ever needs one specific rank.

Once a partition shows which side the target rank must be on, the other side is guaranteed not to contain the answer, its items are all provably too small or too big. There is nothing left to gain by sorting it, so quickselect never even looks at it again.

75. State the rule before it runs: Worked example: find the 3rd smallest…

Hypothesis

Predict first

Worked example: find the 3rd smallest with quickselect is about to be worked. State your hypothesis first: which rule or definition decides this one, and what is the first move it forces? Then watch whether the example agrees with you.

Correct: Partition the whole list around pivot 5, as before

Why: The partition gives 3, 4, 2 (positions 1 to 3), then pivot 5 at position 4, then 9, 7, 8 (positions 5 to 7).

A hypothesis you wrote down is falsifiable; a vague sense of how it will go is not. If the example opens somewhere else, that gap is the thing worth chasing.

76. Worked example: find the 3rd smallest with quickselect

Worked example

Find the 3rd smallest item in 8, 3, 7, 4, 9, 2, 5, counting positions starting at 1.

Partition the whole list around pivot 5, as before

Why: The partition gives 3, 4, 2 (positions 1 to 3), then pivot 5 at position 4, then 9, 7, 8 (positions 5 to 7).

Compare the pivot's position (4) to the target rank (3)

Why: Since 3 is less than the pivot's position 4, the 3rd smallest item must be inside the smaller-side piece, 3, 4, 2, the bigger-side piece can be discarded entirely.

stepcurrent piecepivotpivot's positionnext move
18, 3, 7, 4, 9, 2, 554target 3 < 4, recurse into 3, 4, 2
23, 4, 221 (within this piece)target 3 > 1, recurse into 4, 3, new target is rank 2 within this piece
34, 331 (within this piece)target 2 > 1, recurse into remaining single item, 4

Partition 3, 4, 2 around pivot 2

Why: 2 is smallest, so it lands at position 1 within this piece, leaving the piece 4, 3 after it. The target rank (3) is past position 1, so recurse into 4, 3, now looking for the item at position 2 within that piece.

Partition 4, 3 around pivot 3

Why: 3 is smaller than 4, so 3 lands at position 1 within this piece, leaving the single item 4 after it. The remaining target position (2) is past position 1, so the answer is the last remaining item, 4.

Verify by checking against the fully sorted list

Why: The full sorted order of 8, 3, 7, 4, 9, 2, 5 is 2, 3, 4, 5, 7, 8, 9. The 3rd item in that list is 4, matching what quickselect found, without ever sorting the 9, 7, 8 piece.

77. find the 3rd smallest with quickselect — line by line

Picture it

Animation

Shows: Each line of the worked example "find the 3rd smallest with quickselect", appearing one at a time.

The same working the example does, in the order a tutor would write it.

Takeaway: The full sorted order of 8, 3, 7, 4, 9, 2, 5 is 2, 3, 4, 5, 7, 8, 9. The 3rd item in that list is 4, matching what quickselect found, without ever sorting the 9, 7, 8 piece.

78. Quickselect's average running time is linear

Concept

Each call to quickselect partitions its current piece (a cost proportional to that piece's size), then throws away one whole side and recurses only into the other.

On average, that surviving piece is a constant fraction smaller than the one before it, not the same size, and not just one item smaller. A sum of steadily shrinking piece sizes adds up to only a constant multiple of the original size, giving expected linear total time.

79. What has to happen first: Worked example: why a shrinking sum gives linear time

Ranking

Put in order

Put the moves of Worked example: why a shrinking sum gives linear time into the order they have to happen.

  1. List the piece size at each recursive call
  2. Add up the work across all calls
  3. Verify the total stays under twice the original size

Why: These are the moves of the worked example in the order it makes them, and each one is set up by the one before it. Starting at 16 and roughly halving each time: 16, then 8, then 4, then 2, then 1.

80. Worked example: why a shrinking sum gives linear time

Worked example

Suppose, as an illustration, quickselect's surviving piece is on average about half the size of the one before it. Trace the total work for an original piece of size 16.

List the piece size at each recursive call

Why: Starting at 16 and roughly halving each time: 16, then 8, then 4, then 2, then 1.

callpiece sizework done this call
11616
288
344
422
511

Add up the work across all calls

Why: 16 plus 8 plus 4 plus 2 plus 1 is 31 total.

\[ 16+8+4+2+1 = 31 \]

Verify the total stays under twice the original size

Why: 31 is less than 32, which is twice the original piece size of 16. This is the hallmark of a shrinking geometric sum: no matter how many terms you add, the total never exceeds a small constant multiple of the first term, which is exactly why the total work stays linear in the original size.

\[ 31 < 2(16) = 32 \]

81. Quickselect's worst case is also quadratic

Concept

The same bad-pivot scenario that hurts quicksort hurts quickselect too: a fixed pivot rule that always picks an extreme item, on an input built to exploit it.

If every partition only rules out one item instead of a real fraction of the piece, quickselect ends up scanning nearly the whole list at every single call, adding up to the same quadratic total as quicksort's worst case.

82. Why one-sided recursion is linear

Picture it

Animation

Shows: Why one-sided recursion is linear — a rendered Manim animation.

Rendered with Manim.

Takeaway: The geometric series is what removes the log entirely.

83. Plan first: Worked example: quickselect's worst case on sorted input

Step zero

Discussion prompt

Worked example: quickselect's worst case on sorted input — before any calculation: what is the plan? Name the moves in order, in plain English, without doing the arithmetic.

Hint: It starts with: Partition 1, 2, 3, 4, 5 around pivot 1

Answer:

  1. Partition 1, 2, 3, 4, 5 around pivot 1
  2. Repeat: each partition again picks the smallest item as pivot
  3. Verify the total comparisons match the quadratic pattern

84. Worked example: quickselect's worst case on sorted input

Worked example

Find the 5th (largest) item of the sorted list 1, 2, 3, 4, 5 using quickselect with a pivot rule that always picks the first item.

Partition 1, 2, 3, 4, 5 around pivot 1

Why: 1 is smallest, landing at position 1. The target rank, 5, is past position 1, so recurse into the remaining piece, 2, 3, 4, 5, with the target still at relative rank 4 within it.

callpiece sizepivot positioncomparisons made
1514
2413
3312
4211

Repeat: each partition again picks the smallest item as pivot

Why: Every call rules out exactly one item, the pivot, and recurses into everything else, never skipping any comparisons.

Verify the total comparisons match the quadratic pattern

Why: 4 plus 3 plus 2 plus 1 is 10 comparisons, the same n times (n minus 1) divided by 2 total as quicksort's worst case on this exact input, because quickselect never got to discard a large piece the way it should.

\[ 4+3+2+1 = 10 = \frac{5(5-1)}{2} \]

85. What stays fixed: Worked example: quickselect's worst case on sorted…

Invariant

Step through it

Step through Worked example: quickselect's worst case on sorted input one row at a time. One of these columns never changes — find it, and say why it cannot.

  1. Step 1: call is 1
  2. Step 2: call is 2
  3. Step 3: call is 3
  4. Step 4: call is 4

86. Answer it before you see the options: Check yourself: what does selection…

Prediction

Predict first

Which approach finds the answer fastest on average, and why?

Answer it in your own words, now, with nothing to choose from. The options are on the next slide — and picking the right one off a list is an easier skill than producing it.

Correct: Quickselect: partition and recurse into only the side containing the target rank, discarding the other side entirely.

Why: Quickselect needs the same partition step as quicksort, but after each partition it can discard the entire side that cannot contain the target rank. On average this halves-or-better the remaining work each call, giving expected linear time overall, faster than fully sorting.

87. Check yourself: what does selection actually require?

Check

You need to find the 5th smallest number in an unsorted list of 1,000 numbers, and nothing else about the order of the other numbers matters.

Check your understanding

Which approach finds the answer fastest on average, and why?

  • A. Quickselect: partition and recurse into only the side containing the target rank, discarding the other side entirely. (correct)
  • B. Sort the entire list, then read off the item in position 5, since sorting is the only reliable way to know any item's rank.
  • C. Binary search the unsorted list for position 5 directly, since binary search always finds a target rank in log time.
  • D. Run the full median-of-medians algorithm, since only a worst-case-guaranteed method can be trusted to find a specific rank.

Answer: A

Why: Quickselect needs the same partition step as quicksort, but after each partition it can discard the entire side that cannot contain the target rank. On average this halves-or-better the remaining work each call, giving expected linear time overall, faster than fully sorting.

Why B tempts people
This is the selection-versus-sorting trap: sorting the full list does far more work (n log n) than the question needs, since only one rank was ever asked for, not the order of everything.
Why C tempts people
Binary search only works on data that is already sorted, using comparisons to narrow down a search range. There is no notion of a sorted position to binary search over in an unsorted list.
Why D tempts people
Median-of-medians guarantees worst-case linear time but costs more in practice due to a larger constant factor. When the average case is all that's needed, quickselect is the faster everyday choice; median-of-medians is for when the worst case must be ruled out.

88. We want a pivot rule with a guarantee, not luck

Concept

A random pivot makes quickselect's worst case wildly unlikely, but does not rule it out. Some applications, like real-time systems, need a running time that is guaranteed to be linear, every single time, no exceptions.

That calls for a pivot rule that is chosen deliberately, not randomly, and that can be proven to always produce a good-enough split.

89. What if we could always force a good split?

Intuition

Earlier, a "good" pivot was one landing in the middle half of the piece. A random pivot only lands there about half the time.

What if, instead of hoping, we built a small procedure that always picks a pivot guaranteed to be reasonably central, one that can never be tricked into landing on an extreme item, no matter what the input looks like?

90. Median-of-medians, step 1: split into groups of five

Concept

The median-of-medians pivot rule starts by chopping the whole piece into small groups of five items each (the very last group may have fewer than five if the piece's size doesn't divide evenly).

A piece of size n is split into roughly n divided by 5 such groups.

91. Median-of-medians, steps 2 and 3: median of medians

Concept

Step 2: find the median of each group of five. Since every group only has five items, finding its median is cheap, just a small, fixed number of comparisons, no matter how big the whole piece is.

Step 3: collect all of those group medians into their own small list, then recursively find the median of that list. Use that value as the pivot for the main piece.

92. Median of medians guarantees a decent pivot

Picture it

Animation

Shows: Median of medians guarantees a decent pivot — a rendered Manim animation.

Rendered with Manim.

Takeaway: A worse pivot than random, but with a guarantee attached.

93. Guess the shape of the answer: Worked example: computing a median-of-medians…

Estimation

Predict first

Find the median-of-medians pivot for the 15-item list 12, 3, 17, 5, 9, 20, 1, 14, 8, 22, 6, 11, 19, 2, 15.

Commit before you compute: what does Worked example: computing a median-of-medians pivot come out to? A rough magnitude and the right form is enough — the point is to have something concrete to be wrong about.

Correct: Verify how balanced a split this pivot actually produces

Why: A prediction you can defend turns the computation into a check rather than a leap of faith — and an answer that contradicts it is caught on the spot. Checking all 15 items against 11: seven items (3, 5, 9, 1, 8, 6, 2) are less than 11, one item equals 11, and seven items (12, 17, 20, 14, 22, 19, 15) are greater than 11.

94. Worked example: computing a median-of-medians pivot

Worked example

Find the median-of-medians pivot for the 15-item list 12, 3, 17, 5, 9, 20, 1, 14, 8, 22, 6, 11, 19, 2, 15.

Split the 15 items into 3 groups of five

Why: Group A: 12, 3, 17, 5, 9. Group B: 20, 1, 14, 8, 22. Group C: 6, 11, 19, 2, 15.

Find the median of each group

Why: Sorting each group of five: A sorts to 3, 5, 9, 12, 17 (median 9). B sorts to 1, 8, 14, 20, 22 (median 14). C sorts to 2, 6, 11, 15, 19 (median 11).

groupitemssortedmedian
A12, 3, 17, 5, 93, 5, 9, 12, 179
B20, 1, 14, 8, 221, 8, 14, 20, 2214
C6, 11, 19, 2, 152, 6, 11, 15, 1911

Find the median of the three group medians

Why: The medians are 9, 14, and 11. Sorted, that's 9, 11, 14, the median of these three is 11.

\[ \text{median}(9, 14, 11) = 11 \]

Verify how balanced a split this pivot actually produces

Why: Checking all 15 items against 11: seven items (3, 5, 9, 1, 8, 6, 2) are less than 11, one item equals 11, and seven items (12, 17, 20, 14, 22, 19, 15) are greater than 11. A 7-and-7 split out of 14 remaining items is close to perfectly even, far better than the guarantee alone would require.

95. Fill in: median for Worked example: computing a median-of-medians…

Comparison

Comparison matrix

From Worked example: computing a median-of-medians pivot: refill the median column from what you know. The rest of the table is as it appeared.

groupitemssortedmedian
A12, 3, 17, 5, 93, 5, 9, 12, 179
B20, 1, 14, 8, 221, 8, 14, 20, 2214
C6, 11, 19, 2, 152, 6, 11, 15, 1911

96. Why groups of five, specifically (the setup)

Intuition

Two competing needs shape the group size. Smaller groups mean finding each group's median is even cheaper, but a size guarantee built from tiny groups turns out to be weaker (more on that in the next few slides).

Larger groups give a stronger guarantee, but sorting each group to find its median costs more comparisons per group. Five items is the smallest group size that still produces a guarantee strong enough to make the whole algorithm run in linear time, which is exactly why the trap on the next slide matters.

97. Something is wrong here: misremembering why groups of five are used

Anomaly

Predict first

A student writes this, and it looks reasonable:

A student remembers that the groups must have an odd number of items so that each group has a single, unambiguous median, and concludes that any odd size, 3, 5, 7, 9, would work equally well, with 5 being just a traditional pick.

It is wrong. Say what breaks — and say it before you turn the page.

Correct: Groups of three are odd, so each has a clear middle item, this satisfies the odd-size reasoning, but misses the real requirement.

Oddness explains why every group needs a single median, but it does not explain why five specifically was chosen over three, seven, or nine.

Why: Groups of three are odd, so each has a clear middle item, this satisfies the odd-size reasoning, but misses the real requirement.

98. Trap: misremembering why groups of five are used

Trap

The trap

A student remembers that the groups must have an odd number of items so that each group has a single, unambiguous median, and concludes that any odd size, 3, 5, 7, 9, would work equally well, with 5 being just a traditional pick.

Try groups of three instead of five

Why: Groups of three are odd, so each has a clear middle item, this satisfies the odd-size reasoning, but misses the real requirement.

The fix

Oddness explains why every group needs a single median, but it does not explain why five specifically was chosen over three, seven, or nine.

The real reason involves the recurrence the pivot rule produces, covered fully in the next few slides. Groups of three give a size guarantee too weak to prove linear time; groups of five are the smallest size for which the guarantee is strong enough.

Compare the fraction of guaranteed elements for groups of three versus groups of five

Why: With groups of three, the resulting recurrence's fractions add up to exactly one, not strictly less than one, so the standard argument for linear time does not go through. With groups of five, the fractions add up to nine tenths, strictly below one, which is exactly what makes the linear-time proof work.

\[ \text{groups of 3: } \frac{1}{3}+\frac{2}{3}=1 \qquad \text{groups of 5: } \frac{1}{5}+\frac{7}{10}=\frac{9}{10}<1 \]

99. Which of these survive contact with Quicksort, Selection & Median of Medians?

Two truths and a lie

Sort into buckets

Some of these hold up and some are the exact mistakes this lesson is built to prevent. Sort them.

Holds up
You have named 11 reusable moves so far. Say as many as you can out loud, by number, from memory.; Picture a messy pile of exam papers. You grab one paper at random, call it the pivot, and sort every other paper into a smaller pile or a bigger pile compared to it.; Partitioning does not sort either side, it only guarantees the split is in the right order relative to the pivot. Each side still needs its own sorting pass.
Breaks
A student remembers that quicksort is one of the fast sorting algorithms and assumes its running time is always proportional to n log n, no matter the input or the pivot rule.; Conclude that pivot choice is irrelevant to performance
sound
These are stated as this lesson states them — each one survives the edge cases Quicksort, Selection & Median of Medians puts it through.
flawed
Each of these is lifted from a trap in this deck: reasonable-sounding, and wrong in a way that only shows up once you rely on it.

100. The size guarantee: naming the two chunks

Concept

Before proving anything, name exactly what is being counted. Call n the total number of items in the piece, and call the chosen pivot the median-of-medians value.

The guarantee to prove has two parts: some fraction of all n items are provably less than or equal to the pivot, and that same fraction are provably greater than or equal to it.

\[ \text{at least } \tfrac{3n}{10} \text{ items} \le \text{pivot}, \qquad \text{at least } \tfrac{3n}{10} \text{ items} \ge \text{pivot} \]

101. Process: bounding the median-of-medians split

Intuition

Watch me not know the answer. This is what the first two minutes actually look like.

We need a guarantee that the pivot is never too close to an end. Groups of five, medians taken, then the median of those medians.

Try to prove the pivot is the true median, or close to it

Why: If we could show the pivot lands near position n/2, the recurrence would be the balanced one and we would be done.

It is not close to the median, and it cannot be made to be

Why: Medians of medians can sit well away from the true median. Chasing a tight bound here is chasing something false, and no amount of algebra rescues it.

Dead end. Not a mistake — a move that was worth trying and did not pay off. This happens in most proofs.

Back up. Ask for much less: a constant fraction, not the middle

Why: We do not need near-half. We only need to throw away some fixed fraction every time. Count the elements guaranteed to be on each side and take whatever bound falls out.

\[ \text{at least } \; \tfrac{3}{10}n \; \text{ elements are guaranteed on each side} \]

So the recursive call is on at most 7n/10 elements. Weak, ugly, and completely sufficient. Aiming for the weakest bound that still works is a skill, not a compromise.

The expert does not see the whole path in advance. The expert tries something, reads the result, and adjusts. That is the skill.

102. Where the 30 percent comes from

Picture it

Animation

Shows: Where the 30 percent comes from — a rendered Manim animation.

Rendered with Manim.

Takeaway: A guarantee, bought with a much larger constant.

103. Building the counting argument, one step at a time

Intuition

Start with the groups whose own median is less than or equal to the overall median-of-medians pivot. Since the pivot is itself the median of all the group medians, at least half of the groups have a median in this category.

Now look inside just one of those qualifying groups. It has five items, and its median is less than or equal to the pivot. Within that one group, the median itself plus the two items smaller than it, three items total, are also all less than or equal to the pivot.

Multiply that out: at least half of the groups, each contributing at least three qualifying items, gives a guaranteed count of items less than or equal to the pivot across the whole piece. The exact same argument, mirrored, guarantees the same count for items greater than or equal to the pivot.

104. Guess the shape of the answer: Worked example: verifying the count for n =…

Estimation

Predict first

Apply the counting argument to a piece of 40 items, split into groups of five.

Commit before you compute: what does Worked example: verifying the count for n = 40 come out to? A rough magnitude and the right form is enough — the point is to have something concrete to be wrong about.

Correct: Verify this matches the claimed fraction

Why: A prediction you can defend turns the computation into a check rather than a leap of faith — and an answer that contradicts it is caught on the spot. 3n divided by 10 for n equal to 40 is 12, exactly the count just derived from counting groups and items directly, confirming the guarantee holds for this concrete case.

105. Worked example: verifying the count for n = 40

Worked example

Apply the counting argument to a piece of 40 items, split into groups of five.

Find the number of groups

Why: 40 items divided into groups of five gives 8 groups total.

\[ \frac{40}{5} = 8 \text{ groups} \]

Find how many of those groups have a median less than or equal to the pivot

Why: At least half of the 8 groups qualify, since the pivot is the median of all 8 group medians.

\[ \frac{8}{2} = 4 \text{ qualifying groups} \]

Count guaranteed items from those qualifying groups

Why: Each qualifying group contributes at least 3 items (its median plus the two items below it) that are also less than or equal to the overall pivot.

\[ 4 \times 3 = 12 \text{ items} \le \text{pivot} \]

Verify this matches the claimed fraction

Why: 3n divided by 10 for n equal to 40 is 12, exactly the count just derived from counting groups and items directly, confirming the guarantee holds for this concrete case.

\[ \frac{3(40)}{10} = 12 \ \checkmark \]

106. verifying the count for n = 40 — line by line

Picture it

Animation

Shows: Each line of the worked example "verifying the count for n = 40", appearing one at a time.

The same working the example does, in the order a tutor would write it.

Takeaway: 3n divided by 10 for n equal to 40 is 12, exactly the count just derived from counting groups and items directly, confirming the guarantee holds for this concrete case.

107. This bounds the worst-case recursive call

Concept

If at least three tenths of the n items are guaranteed to be less than or equal to the pivot, and the mirrored argument guarantees the same fraction is greater than or equal to it, then neither side of the partition can hold more than the remaining seven tenths.

\[ n - \frac{3n}{10} = \frac{7n}{10} \]

No matter how the rest of the items happen to fall, the larger recursive call, the one a worst-case adversary would want to make as big as possible, is capped at seven tenths of n. This is a guarantee, not an average.

108. The full recurrence for median-of-medians

Concept

Selecting with this pivot rule involves three costs: recursively finding the median of the roughly n divided by 5 group medians, recursively selecting within the larger side of the partition (at most seven tenths of n), and the work of grouping, finding each group's median, and partitioning, all proportional to n.

\[ T(n) = T\!\left(\frac{n}{5}\right) + T\!\left(\frac{7n}{10}\right) + O(n) \]

Both recursive pieces are strictly smaller than n, and their sizes are both guaranteed, not just typical or average.

109. Recurse into the smaller side first

Picture it

Animation

Shows: Recurse into the smaller side first — a rendered Manim animation.

Rendered with Manim.

Takeaway: A one-line change that removes the stack-overflow risk entirely.

110. Why the fractions adding to less than one is what saves us

Intuition

Add up the two recursive fractions: one fifth plus seven tenths equals nine tenths.

\[ \frac{1}{5} + \frac{7}{10} = \frac{9}{10} \]

Since nine tenths is strictly less than one whole, the two recursive calls together always cover somewhat less total work than the level above them, the total work per level shrinks by a constant factor as the recursion goes deeper, the same shrinking-sum pattern that made quickselect's average case linear.

111. Decision point: the fractions add to less than one

Intuition

What move should we make next?

The median-of-medians recurrence, with both recursive calls:

\[ T(n) \le T(n/5) + T(7n/10) + O(n) \]

\[ \frac{1}{5} + \frac{7}{10} = \frac{9}{10} < 1 \]

You solved a recurrence with exactly this shape two lessons ago. Which move, and what do you expect the per-level work to do?

_Look at your toolkit. Say a move number out loud before this slide advances._ A wrong guess is useful. A silent guess is not.

112. Plan first: Worked example: verifying the recurrence resolves to linear…

Step zero

Discussion prompt

Worked example: verifying the recurrence resolves to linear time — before any calculation: what is the plan? Name the moves in order, in plain English, without doing the arithmetic.

Hint: It starts with: Find the total size handed to the next level of recursion

Answer:

  1. Find the total size handed to the next level of recursion
  2. Repeat for a few more levels
  3. Add up the per-level costs
  4. Verify the total stays within a constant multiple of the original size

113. Worked example: verifying the recurrence resolves to linear time

Worked example

Illustrate the shrinking-sum pattern starting from a piece of size 1,000.

Find the total size handed to the next level of recursion

Why: The two recursive pieces have sizes n divided by 5 and 7n divided by 10; together they add up to nine tenths of n.

\[ \frac{1000}{5} + \frac{7(1000)}{10} = 200 + 700 = 900 \]

Repeat for a few more levels

Why: Each level's total size is nine tenths of the level above: 1000, then 900, then 810, then 729, and so on, shrinking by the same constant factor every time.

leveltotal size at this level
01000
1900
2810
3729

Add up the per-level costs

Why: Total work is proportional to 1000 plus 900 plus 810 plus 729 and so on, a shrinking geometric sum with ratio nine tenths, which converges to a bounded constant multiple of 1000, exactly like the earlier quickselect sum converged to a constant multiple of its starting size.

Verify the total stays within a constant multiple of the original size

Why: A geometric sum with a ratio strictly less than one and first term proportional to n always totals to at most a fixed constant times n, here, that constant works out to 10, since the sum of nine-tenths raised to every power converges to 10. So the total work is proportional to n, confirming linear worst-case time.

\[ 1000 + 900 + 810 + 729 + \cdots \le 10(1000) \]

114. verifying the recurrence resolves to linear time — line by line

Picture it

Animation

Shows: Each line of the worked example "verifying the recurrence resolves to linear time", appearing one at a time.

The same working the example does, in the order a tutor would write it.

Takeaway: A geometric sum with a ratio strictly less than one and first term proportional to n always totals to at most a fixed constant times n, here, that constant works out to 10, since the sum of nine-tenths raised to every power converges to 10. So the total work is proportional to n, confirming linear worst-case time.

115. Why the fractions adding to less than one is the whole game

Concept

The move: #11 (Unroll and sum the levels), then #3 (Drop the tail).

Unroll and look at the per-level work

Why: Level 0 does n. Level 1 does 9n/10. Level 2 does 81n/100. Each level is 9/10 of the one above it.

\[ n + \tfrac{9}{10}n + \left(\tfrac{9}{10}\right)^{2}n + \cdots = \frac{n}{1 - 9/10} = 10n \]

Drop the tail to see it is really linear

Why: The series is dominated by its first term. All the levels below the root together add up to at most nine times the root — a constant multiple, so the whole thing is Theta of n.

If the fractions had summed to exactly 1, every level would cost n and you would get n log n. Above 1, the leaves dominate and it blows up. That one comparison decides the answer, and it is the same comparison the Master Theorem makes.

116. Decode the notation: Why the fractions adding to less than one is the whole…

Notation

Annotate

From Why the fractions adding to less than one is the whole game — read this one piece at a time. What is each part doing?

On: \( n + \tfrac{9}{10}n + \left(\tfrac{9}{10}\right)^{2}n + \cdots = \frac{n}{1 - 9/10} = 10n \)

  • Level 0 does n. Level 1 does 9n/10. Level 2 does 81n/100. Each level is 9/10 of the one above it.
  • The series is dominated by its first term. All the levels below the root together add up to at most nine times the root — a constant multiple, so the whole thing is Theta of n.

117. Median-of-medians guarantees linear worst-case selection

Concept

Because the pivot is chosen deliberately rather than at random, the seven-tenths bound on the larger recursive call holds for every single input, not just on average.

\[ T(n) = O(n) \text{ in the worst case, guaranteed} \]

This closes the gap left by quickselect: quickselect is linear on average but quadratic on some adversarial inputs; median-of-medians is linear on every input, including the ones built to defeat a naive pivot rule.

118. Finding the k-th does not need a sort

Picture it

Animation

Shows: Finding the k-th does not need a sort — a rendered Manim animation.

Rendered with Manim.

Takeaway: Sorting answers a much harder question than the one asked.

119. Constant factors: why quickselect still gets used

Intuition

"Linear time" hides a constant factor, and median-of-medians has a noticeably larger one, grouping the whole piece, sorting every group of five, and recursing twice per call all add real overhead that a simple random pivot never pays.

In everyday code, where the input isn't hand-crafted to attack a specific pivot rule, randomized quickselect's expected linear time with a small constant usually beats median-of-medians' guaranteed linear time with a larger one.

120. Choosing between quickselect and median-of-medians

Concept

Use randomized quickselect when average-case speed is what matters and an astronomically unlikely bad case is an acceptable risk, which describes most everyday selection tasks.

Use median-of-medians (or run quickselect with a median-of-medians pivot only when needed) when the running time must be bounded no matter what, such as in a system where a worst-case guarantee is a hard requirement, not just a nice-to-have.

121. Teach it back: Choosing between quickselect and median-of-medians

Explain it

Discussion prompt

Explain Choosing between quickselect and median-of-medians to a student a year behind you. No notation, no jargon they have not met — and it still has to be true.

Hint: If your explanation needs a symbol they have never seen, you are describing the notation rather than the idea.

Answer:

Use randomized quickselect when average-case speed is what matters and an astronomically unlikely bad case is an acceptable risk, which describes most everyday selection tasks.

122. Choosing between them

Picture it

Animation

Shows: Choosing between them — a rendered Manim animation.

Rendered with Manim.

Takeaway: Worst-case guarantees versus practical speed.

123. What has to happen first: Worked example: median-of-medians selection end to end

Ranking

Put in order

Put the moves of Worked example: median-of-medians selection end to end into the order they have to happen.

  1. Reuse the median-of-medians pivot already computed
  2. Partition all 15 items around pivot 11
  3. Compare the pivot's position (8) to the target rank (8)
  4. Verify by checking against the fully sorted list

Why: These are the moves of the worked example in the order it makes them, and each one is set up by the one before it. The groups of five gave medians 9, 14, and 11, and the median of those three medians is 11, that is this call's pivot.

124. Worked example: median-of-medians selection end to end

Worked example

Find the median (the 8th smallest of 15 items) of the same list from before: 12, 3, 17, 5, 9, 20, 1, 14, 8, 22, 6, 11, 19, 2, 15.

Reuse the median-of-medians pivot already computed

Why: The groups of five gave medians 9, 14, and 11, and the median of those three medians is 11, that is this call's pivot.

Partition all 15 items around pivot 11

Why: As found earlier, 7 items are less than 11, 1 item equals 11 (the pivot itself), and 7 items are greater than 11, pivot 11 lands at position 8 in the fully partitioned order.

quantityvalue
items less than pivot7
pivot's position8
items greater than pivot7
target rank8

Compare the pivot's position (8) to the target rank (8)

Why: They match exactly, so the pivot itself is the answer, no further recursion is needed on either side.

Verify by checking against the fully sorted list

Why: Sorting all 15 items gives 1, 2, 3, 5, 6, 8, 9, 11, 12, 14, 15, 17, 19, 20, 22. The 8th item in that list is 11, matching the pivot found, and it took just one partition, since the median-of-medians pivot happened to land exactly on the target rank this time.

125. Which is which, by value

Discrimination

Sort into buckets

Sort these by value, from memory, without looking back at Worked example: median-of-medians selection end…. Telling them apart on the spot is the skill; the table is only where the answer happens to be written down.

7
items less than pivot; items greater than pivot
8
pivot's position; target rank
g1
value is "7" for items less than pivot, items greater than pivot — that is what the table on "Worked example: median-of-medians…" records, and it is the single property separating this group from the rest.
g2
value is "8" for pivot's position, target rank — that is what the table on "Worked example: median-of-medians…" records, and it is the single property separating this group from the rest.

126. Check yourself: why groups of five

Check

The median-of-medians pivot rule splits the piece into groups of five items each.

Check your understanding

Why does using groups of five (rather than groups of three) guarantee linear worst-case running time?

  • A. With groups of five, the resulting recurrence's fractions (one fifth and seven tenths) add to nine tenths, strictly less than one, so the total work shrinks level by level; with groups of three, the fractions add to exactly one, which does not. (correct)
  • B. Groups of five are the largest group size for which finding a median is still cheap, so any larger group would make each level too slow.
  • C. Any odd group size works equally well for the size guarantee; five was chosen only because it keeps the arithmetic simple.
  • D. Groups of five can always be sorted using a single comparison, making the per-group cost effectively free.

Answer: A

Why: The size guarantee groups of five produce leads to the recurrence T(n) = T(n/5) + T(7n/10) + O(n), and one fifth plus seven tenths is nine tenths, strictly below one. Groups of three instead lead to fractions that add to exactly one, which is not strictly below one and does not give the same linear-time guarantee.

Why B tempts people
This gets the direction backwards: five is not the largest workable size, it is the smallest one for which the fraction sum drops below one. Larger odd sizes (like seven) also work, just with somewhat more per-group overhead.
Why C tempts people
This is the exact misconception this lesson targets. Oddness only guarantees a single well-defined median per group; it does not guarantee the fraction sum in the recurrence comes out below one, which is what groups of three fail to do.
Why D tempts people
Sorting five elements to find a median takes a small constant number of comparisons, not one, and it is never literally free, just cheap enough not to depend on the size of the whole piece.

127. Rule out three: Check yourself: the guaranteed split size

Elimination

Eliminate the wrong options

The median-of-medians pivot is guaranteed to have at least how many of the 40 items less than or equal to it?

3 of these 4 are wrong. Strike them one at a time, and say what rules each one out before you strike the next. The survivor is the answer.

  • A. 12, from at least 4 qualifying groups, each contributing at least 3 items.
  • B. 20, because the median-of-medians pivot always lands exactly at the true middle of the piece.
  • C. 8, one item from each of the 8 groups.
  • D. 28, the count guaranteed on the greater-than-or-equal-to side, not the less-than-or-equal-to side.

Survives elimination: A

Why: At least half of the 8 groups (4 groups) have a median less than or equal to the overall pivot, and each such group contributes at least 3 items (its median plus the two items below it) that are also less than or equal to the pivot, 4 times 3 is 12, matching 3n divided by 10 for n equal to 40.

128. Check yourself: the guaranteed split size

Check

A piece has 40 items, split into 8 groups of five for the median-of-medians pivot rule.

Check your understanding

The median-of-medians pivot is guaranteed to have at least how many of the 40 items less than or equal to it?

  • A. 12, from at least 4 qualifying groups, each contributing at least 3 items. (correct)
  • B. 20, because the median-of-medians pivot always lands exactly at the true middle of the piece.
  • C. 8, one item from each of the 8 groups.
  • D. 28, the count guaranteed on the greater-than-or-equal-to side, not the less-than-or-equal-to side.

Answer: A

Why: At least half of the 8 groups (4 groups) have a median less than or equal to the overall pivot, and each such group contributes at least 3 items (its median plus the two items below it) that are also less than or equal to the pivot, 4 times 3 is 12, matching 3n divided by 10 for n equal to 40.

Why B tempts people
Median-of-medians only guarantees a good-enough split, not an exact median. The true median would need to sit at exactly position 20, but the guarantee is a floor of 12, not an exact value, the actual pivot can land anywhere at or beyond that floor.
Why C tempts people
This confuses the number of groups (8) with the guaranteed item count. Each qualifying group contributes 3 items, not 1, and only about half the groups qualify for this side of the count.
Why D tempts people
28 is the guaranteed cap on the larger recursive call (7n divided by 10), which is a different quantity from the 3n divided by 10 guaranteed count on one side of the pivot, swapping the two mixes up which bound answers which question.

129. Real-world sorts hedge their bets

Concept

Many production sorting libraries don't choose purely between plain quicksort and a worst-case-guaranteed method, they combine ideas from both.

A common strategy: run ordinary randomized quicksort for its fast average case, but keep track of how deep the recursion goes. If the recursion ever runs suspiciously deep, a sign of an unlucky or adversarial input, switch over to a method with a guaranteed running time for the rest of the work, so the total never blows up to quadratic.

130. By analogy: Real-world sorts hedge their bets

Analogy

Discussion prompt

Explain Real-world sorts hedge their bets by analogy to something with no CS3000 Algorithms in it at all — a queue, a recipe, a map, a bank balance, whatever fits. Then say where your analogy breaks.

Hint: An analogy that never breaks is not an analogy, it is the same idea wearing a hat. Find the seam — that is the part that is actually new.

Answer:

Many production sorting libraries don't choose purely between plain quicksort and a worst-case-guaranteed method, they combine ideas from both.

131. Quicksort sorts in place

Picture it

Animation

Shows: Quicksort sorts in place — a rendered Manim animation.

Rendered with Manim.

Takeaway: The memory advantage that keeps it in standard libraries.

132. Toolkit update

Concept

Moves added today: none.

That is a result, not a gap. Everything in this lesson was proved with moves you already owned.

Moves you reused today:

Move #2 showed up in a new costume today: finding the input that forces quicksort's worst case is exactly building the value that breaks a claimed bound.

Full toolkit so far: #1 through #11.

Next session opens with you naming every one of these from memory, before any new material.

133. Break it if you can: Toolkit update

Counterexample

Discussion prompt

Move #2 showed up in a new costume today: finding the input that forces quicksort's worst case is exactly building the value that breaks a claimed bound.

That is stated as though it always holds. Do one of two things: produce a case where it fails, or say precisely what rules such a case out. "It just does" is not on the menu.

Hint: Hunt at the extremes first — zero, one, negative, empty, equal. If every extreme survives, the reason they survive is the proof.

Answer:

Next session opens with you naming every one of these from memory, before any new material.

134. Connect it up: Quicksort, Selection & Median of Medians

Connect it up

Draw it

One page, no notation unless you need it: draw how these connect — How to reason about quicksort's running time · Toolkit check-in: name them before you look · Quicksort in one sentence · Splitting one pile into two · What it means for a list to be "partitioned". Put an arrow wherever one of them is what makes another possible, and label the arrow with why.

135. What you can do now

Recap

Quicksort, quickselect, and median-of-medians all lean on the same partition step, applied with different goals.

AlgorithmGoalGuaranteed worst case
QuicksortFully sort the listQuadratic with a fixed, exploitable pivot rule
Randomized quicksortFully sort the listQuadratic in principle, but astronomically unlikely
QuickselectFind one rankLinear on average; quadratic with a fixed, exploitable pivot rule
Quickselect with median-of-mediansFind one rankLinear, guaranteed on every input

The pivot rule is never a minor detail, it is the single choice that decides whether an algorithm's worst case is a real risk or an all-but-impossible coincidence.

Sources

  1. Cormen, Leiserson, Rivest & Stein, Introduction to Algorithms, 3rd ed., Ch. 7 (Quicksort) and Ch. 9 (Medians and Order Statistics) — MIT Press, 2009.
  2. Kleinberg & Tardos, Algorithm Design, Ch. 13.5 (A Randomized Algorithm for Selection) — Pearson, 2005.
  3. All recurrences, probability arguments, and numeric traces (partition traces, comparison counts, median-of-medians group computations, and the n=40 / n=1000 counting and recurrence illustrations) re-derived and hand-checked. — Verified 2026-07-18.
  4. Northeastern University CS 3000, Algorithms and Data (Summer 2026) — course page and syllabus — course.ccs.neu.edu/cs3000su26. Sets Cormen, Leiserson, Rivest and Stein, Introduction to Algorithms (3rd ed.) as the textbook; listings follow its conventions.
  5. CS 3000 course notes and midterm references circulated by students — github.com/vigneshsaravanakumar404/CS-3000-Algorithms-Data. Notes are typeset with the algpseudocode package, which is the style the listings in this deck follow.

Want this taught 1-on-1? Alexander tutors CS3000 Algorithms — $55/session, free consultation.

Book on Wyzant · Text (657) 465-8108