Exercises — Merge sort — divide and conquer, O(n log n), stable, proof of correctness
Quick reminders (so you never hit an undefined term):
- = number of elements in the array.
- comparison = one "is ?" question between two elements.
- write = placing one element into the output array.
- stable = equal keys keep their original left-to-right order.
- merge = the two-pointer routine that fuses two already-sorted lists.
L1 — Recognition
Exercise 1.1
Which single line of the merge routine is responsible for stability, and what would break if you changed it?
Recall Solution
The line if A[i] <= B[j]:. The <= means: on a tie, take the LEFT list's element first. Since the left list holds elements that came earlier in the original array, equal keys stay in original order — that's exactly stability. Change it to < and on a tie you'd take the right element first, swapping equal records → not stable.
Exercise 1.2
Order these three step labels into the correct merge-sort sequence, and say which one does zero comparisons: Combine, Divide, Conquer.
Recall Solution
Correct order: Divide → Conquer → Combine.
- Divide splits at
mid = len//2— this does zero comparisons, just arithmetic. - Conquer recursively sorts each half.
- Combine = merge, where all the comparisons actually happen.
Exercise 1.3
State merge sort's best, average, and worst time, and its space. One sentence on why best = worst.
Recall Solution
Best = Average = Worst = ; Space (extra array). Why best = worst: the structure never changes with input — merge sort always splits exactly in half and always merges in regardless of whether the input is already sorted, reversed, or random. See Big-O Notation.
L2 — Application
Exercise 2.1
Fully trace merge_sort([8, 3, 5, 1]). Give the split tree and every merge step with the comparison made.
Recall Solution
Refer to the recursion tree in the figure below.

- Split
[8,3,5,1]→[8,3]and[5,1](mid = 4//2 = 2). [8,3]→[8],[3]; merge: cmp 8 vs 3 → 3 smaller →[3,8].[5,1]→[5],[1]; merge: cmp 5 vs 1 → 1 smaller →[1,5].- Merge
[3,8]&[1,5]:- cmp 3 vs 1 → take 1 →
[1] - cmp 3 vs 5 → take 3 →
[1,3] - cmp 8 vs 5 → take 5 →
[1,3,5] - right list empty → copy 8 →
[1,3,5,8]✓
- cmp 3 vs 1 → take 1 →
Exercise 2.2
Merge these two sorted lists by hand, listing each comparison: Assume records are tagged 's twos as and 's two as . Show that stability keeps 's twos before 's.
Recall Solution
Using <= (prefer left = on ties):
- cmp ? yes → take → out
- cmp ? yes → take → out
- cmp ? no → take → out
- cmp ? no → take → out
- empty → copy → … wait, careful: after taking 4, is empty, then copy leftover of = .
- Final: . All of 's twos () come before 's two () → stability preserved. See Stability of Sorting Algorithms.
Exercise 2.3
For , use the recurrence to state the number of merge layers and the total work per layer.
Recall Solution
Layers to reach size 1: , plus the size-1 base level → total depth levels. Each level does work (level has problems of size , and ). So total , i.e. .
L3 — Analysis
Exercise 3.1
What is the exact maximum number of comparisons to merge two lists whose total length is ? Prove why it's and not .
Recall Solution
Maximum . Proof: every comparison outputs at least one element (the smaller front). After comparisons, at least elements are placed. The loop stops the moment one list empties; at worst that happens right after the second-to-last element is placed, i.e. after comparisons. The final remaining element is copied with no comparison. Hence at most . Worst case is achieved when the two lists interleave perfectly, e.g. , .
Exercise 3.2
Give the exact worst-case comparison count for merging and , and confirm it equals .
Recall Solution
Trace: cmp(1,2)→1; cmp(3,2)→2; cmp(3,4)→3; cmp(5,4)→4; cmp(5,6)→5; then empty, copy 6 (no cmp). That's 5 comparisons, and . ✓ Perfect interleaving forces the maximum.
Exercise 3.3
Merge sort vs insertion sort: for the reverse-sorted input of size , insertion sort does comparisons. Merge sort does . Compute both and give the ratio.
Recall Solution
- Insertion (worst): .
- Merge (upper bound): .
- Ratio . Merge sort does about 51× fewer comparisons here. This gap is the whole point of vs .
L4 — Synthesis
Exercise 4.1
Modify merge sort to count inversions (pairs with ). Explain where in merge the count is incremented, and trace it on .
Recall Solution
During merge, when you take an element from the right list B[j] while the left list A still has elements remaining, every one of those remaining left elements is greater than B[j] (both lists sorted) — so add to the inversion count.
Trace on (true inversions: = 3):
- Split → and (deeper merges within each half add 0 inversions here since each is already sorted).
- Merge (left, ) with (right, ):
- cmp 2 vs 1 → take 1 from right; left has 2 elements remaining → add 2.
- cmp 2 vs 3 → take 2 from left.
- cmp 4 vs 3 → take 3 from right; left has 1 element (the 4) remaining → add 1.
- cmp 4 vs 5 → take 4 from left.
- right leftover 5 → copy.
- Total inversions . ✓ Matches the brute-force count.
Exercise 4.2
You have a 100 GB file that does not fit in RAM (8 GB). Explain how the merge primitive lets you sort it, and why the divide step maps onto reading chunks. Which vault topic names this technique?
Recall Solution
This is external sorting — see External Sorting.
- Divide/Conquer: read the file in chunks that do fit in RAM (say 4 GB each → 25 chunks), sort each chunk in memory, write each back as a sorted "run" on disk.
- Combine: do a -way merge of the 25 sorted runs. Merge only needs the front of each run in memory at a time — exactly the two-pointer idea generalized to pointers. You stream elements out to the final file, always emitting the smallest current front. Merge sort's key property — that merging needs only sorted inputs, never the whole thing in memory — is precisely what makes it the algorithm of choice for data too big for RAM. (Quicksort, which needs random access, does not adapt as cleanly — see Quick sort.)
L5 — Mastery
Exercise 5.1
Prove, using the loop invariant and strong induction, that merge_sort returns a sorted permutation. Then pinpoint the one step where the inductive hypothesis (IH) is used, and explain what goes wrong if you tried to prove it by weak induction (only assuming correctness for ).
Recall Solution
Merge loop invariant: before each iteration, out is sorted and every element of out is every unconsumed element of both inputs.
- Init:
out=[]— vacuously true. - Maintenance: we append . It is everything already in
out(invariant) and all remaining (inputs sorted). Both properties survive. - Termination: one list empties; the leftover is already sorted and all of
out, sooutbecomes a sorted permutation of . ✓
Strong induction on :
- Base : trivially sorted, its own permutation. ✓
- IH: assume correctness for all lengths .
- Step: split into
leftof size andrightof size , both . The one place the IH is used is here: we assert both recursive calls return sorted permutations — that's licensed by IH because both sizes are strictly less than . Then merge (proven correct above) fuses them.
Why weak induction fails: weak induction only gives you correctness for . But the recursive calls have size , which for is not . You'd have no license to assume the size- calls are correct. Strong induction (all sizes ) is exactly what covers the subproblems. See Recursion and Induction.
Exercise 5.2
Use the Master Theorem to solve and confirm it matches the recursion-tree answer .
Recall Solution
Master Theorem form: with , , . Compute the watershed exponent . Compare with : they're the same order → Case 2. Case 2 gives . ✓ Identical to the recursion-tree result.
Exercise 5.3
A student claims: "If I merge with < instead of <=, the array is still sorted, so the algorithm is still correct." Is the sortedness claim true? Is the algorithm's specification still met? Resolve the apparent contradiction.
Recall Solution
- Sortedness: ✅ true — with
<, ties are still resolved (just favoring the right element), and the output is still non-decreasing. So if the spec is "return a sorted permutation,"<is correct. - Stability spec: ❌ broken — if the spec additionally requires "equal keys keep original order," then
<violates it by taking right-half equals first. Resolution: there's no contradiction — correctness is relative to a specification.<satisfies the weaker (sorted-only) spec but not the stronger (sorted + stable) spec. The parent note's algorithm uses<=precisely to meet the stronger spec.
Connections
- Merge sort (parent) — definitions and proofs these exercises drill.
- Master Theorem — used in Exercise 5.2.
- Recursion and Induction — the strong-induction backbone of L5.
- External Sorting — Exercise 4.2's real-world payoff.
- Stability of Sorting Algorithms — Exercises 1.1, 2.2, 5.3.
- Big-O Notation — the vs comparison.
- Quick sort — contrast noted in 4.2.