🎯 Objective: partition around a pivot, recurse both sides ➔ heavy-split / trivial-combine D&C sort, no merge.
📦 Core Components:Partition ➔ smaller left, larger right | Pivot ➔ lands final | Recurse ➔ both sides.
⚡ Key Constraint: in-place partition + smallest constant ➔ but Θ(N2) on bad pivots; pivot choice is the whole game — and only a Median of Medians pivot converts “improbable” into “impossible”.
📝 How It Works
1. The Algorithm (Partition → Recurse)
Non-trivial split ➔ partition: smaller elements left of pivot, larger right ➔ Partitioning (Quicksort).
Trivial combine ➔ the pivot is already final, so the returned boundary is excluded from both recursive calls; recurse until a partition has size 1.
Mirror of Merge Sort ➔ merge sort splits trivially and combines expensively; quicksort splits expensively and combines for free. Both pay Θ(N) per level — the difference is where.
2. Partitioning — the Scheme Is a Separate Decision
Three schemes taught ➔ out-of-place (Θ(N) extra space) · Hoare’s (in-place, ≤1 swap per item) · Lomuto’s (in-place, more swaps, simplest) ➔ invariants and code in Partitioning (Quicksort).
3-way / Dutch national flag ➔ partition into <p, =p, >p and recurse only on the outer two ⟹ the all-duplicates input drops from Θ(N2) to Θ(N), and depth becomes O(logd) for d distinct keys.
The choice never changes the complexity class(except the 3-way case) ➔ all schemes are Θ(N) comparisons per level; they differ in writes and space, which matters when records are large ➔ Sorting Problem.
3. Pivot Selection
Balance need not be perfect ➔ a median-ish pivot gives log2N levels × Θ(N); even a fixed 1:9 split gives depth log10/9N=Θ(logN) ⟹ still Θ(NlogN). Only a split lopsided by a constant NUMBER of elements at every level reaches Θ(N2) — that is the one question to ask of any pivot rule.
Pivot policy
Cost to choose
Worst case
Triggered by
Verdict
First / last element
O(1)
Θ(N2)
already-sorted input
never — sorted input is the common case, not a rare one
Minimum (or maximum) element
—
Θ(N2)
every input
worst andbest are Θ(N2) — the split is empty:N−1 always
10th-percentile element
—
Θ(NlogN)
nothing
fine — a constant fraction gives k=log10/9N=Θ(logN) levels
Average (mean) element
Θ(N)
Θ(N2)
ai=i! and similar skewed sequences
fails — the mean can sit arbitrarily far from the median
The mean is not the median ➔ tempting and wrong. On ai=i! the mean is ≥nn!=(n−1)!, so the pivot is always the second-largest element ⟹ T(N)=T(N−2)+Θ(N)=Θ(N2).
The general lesson (LO1) ➔ this is the failure mode of any Divide and Conquer design that does not guarantee proportional reduction — the same reason Binary Search works and a “shrink by one” search does not.
4. Ensuring the Worst Case Never Occurs
Randomisation is a probability claim ➔ it makes the Θ(N2) input impossible to construct in advance, since the split no longer depends on the input’s arrangement; it does not bound any individual run. Lecturer’s verdict: in reality a random pivot works well enough on probability alone.
An exact median is not the fix ➔ computing it with Quickselect inherits quickselect’s own Θ(N2) worst case ➔ Quickselect §5.
Median of Medians is the guarantee ➔ a provable 30/70 split at every level ⟹ depth O(logN) ⟹ Θ(NlogN)worst case, at a constant factor large enough that practice still prefers random pivots.
The exam framing ➔ “how do you ensure the worst case never occurs?” asks you to distinguish expected from worst-case bounds, then name a mechanism that upgrades one to the other ➔ Algorithmic Complexity.
Introsort — the engineering answer ➔ run randomised quicksort but count the recursion depth; past ≈2log2N, abandon and finish with Heapsort ⟹ Θ(NlogN) worst case at quicksort’s average constant. (🔭 Beyond the lecture — named only because it is what real libraries ship.)
Unstable as written ➔ partition swaps across long distances, throwing equal keys past one another — the mechanism that makes selection sort unstable; each scheme fails for its own reason ➔ Partitioning (Quicksort) §2–§5.
Universal fallback ➔ index-tagging works here as on any comparison sort, at Θ(N) space and no time penalty ➔ Sorting Problem §5.
💡 Common Mistake:Sorting the =p block ➔ under a 3-way split the middle region is already final; including it in either recursive call restores the duplicate-key blow-up the split was built to remove.
When It Flips: a quicksort run mirrors the BST shape of inserting the same pivots, and its no-merge, cache-friendly, in-place partition gives the smallest constant among Θ(NlogN) sorts — choose it unless a worst-case bound (Heapsort) or stability (Merge Sort) is required; merge also wins for linked lists and external data. Making quicksort stable costs Θ(N) either way, at which point merge sort's scratch is free. Switch to a 3-way partition once duplicates are common, and to Quickselect the moment only one rank is wanted.
📊 Exam Execution Trace & Applied Exercises
Manual Execution Trace — the average-case height argument
Colour the middle half of the pivot positions green (N/4 to 3N/4). A uniformly random pivot is green with probability 21, and the worst green pivot leaves a larger side of 43N.
Level
Largest subproblem if every level is green
Work at this level
0
N
≤cN
1
43N
≤cN
2
169N
≤cN
h
N(43)h=1
base case reached
N(43)h=1green only half the timeΘ(logN)levels×Θ(N)per level⟹h=log4/3N⟹expected depth≈2h=2log4/3N=Θ(logN)⟹Tavg(N)=Θ(NlogN)
Read the result: the change-of-base rule licenses the last step — logaN and logbN differ by the constant logba, so the base is invisible to the complexity class (though very visible in practice).
Applied Exercise — average case from the recurrence (NOT EXAMINABLE)
Problem: with partitioning costed at N+1 operations and the pivot equally likely at any rank k, derive the average-case bound directly.
T(N)NT(N)(N−1)T(N−1)(A)−(B):T(N)telescoping to T(1)=b:T(N)=(N+1)+N1k=1∑N[T(N−k)+T(k−1)]=(N+1)+N2k=1∑NT(k−1)=N(N+1)+2k=1∑NT(k−1)(A)=N(N−1)+2k=1∑N−1T(k−1)(B)=2+NN+1T(N−1)=2+b(N+1)+2(N+1)k=3∑Nk1≤2+b(N+1)+2(N+1)lnN
Final Extracted Output:T(N)=O(NlogN). Two moves carry it — subtracting the (N−1) instance to kill the summation, and bounding the harmonic tail by ∫1Nxdx=lnN. Learn the technique; the derivation is off the exam.
Applied Exercise — matching n locks to n keys in Θ(nlogn)(applied W4)
Problem: a key can be tried in a lock (too big / too small / fits), but two keys cannot be compared to each other, nor two locks. Match them all.
The move: partition needs only one comparable pair, so use a lock as the pivot for the keys, then the matching key as the pivot for the locks.
Step 1: n trials find the fitting key;Step 2: n−1 trials split the locks⇒T(n)=2T(n/2)+Θ(n)=Θ(nlogn)
Final Extracted Output:Θ(nlogn) average. The transferable move is cross-pivoting: when the comparison model forbids comparing within a set, pivot each set on an element of the other set. The bound is average-case for the same reason quicksort’s is — an adversarial lock order still gives Θ(n2).
⚠️ Common Mistakes
💡 Calling quicksort in-place ➔ the partition is in-place; the sort is not, because Θ(logN) recursion frames are auxiliary space.
💡 Worst case needs lopsided-at-every-level ➔ one bad split is harmless; Θ(N2) requires a constant-size split at every level. A 1:9 split is still Θ(NlogN).
💡 Worrying about the log base ➔ 2log4/3N, log2N and lnN are the same complexity class by change of base; quote a base only when discussing constants.
🧠 Active Recall
Derive quicksort's average-case height without the full recurrence.
Hint: Give the middle half of the pivot positions a colour and count.
Answer
Short answer: a pivot lands in the middle half with probability 21; the worst such split leaves 43N, so a green-only run has depth h=log4/3N, and averaging one green level per two gives ≈2h=Θ(logN) ⟹ Θ(NlogN).
Why:Constant fraction ⟹ logarithmic depth ➔ solve N(3/4)h=1; the factor 2 and the base 4/3 are both constants erased by change of base ➔ Solving Recurrences (Telescoping).
"Ensure the worst case never occurs." Distinguish what randomisation gives you from what Median of Medians gives you.
Hint: One statement quantifies over inputs, the other over runs.
Answer
Short answer: randomisation makes the bad case unconstructible; Median of Medians makes it impossible.
Why:Expected vs worst-case bound ➔ with a random pivot the split no longer depends on the input’s arrangement, so no adversary can pre-build a killer input — but an unlucky run is still permitted and Θ(N2) remains the worst-case bound. A deterministic 30/70 guarantee changes the bound itself, at a constant so large that practice keeps randomisation.
Quicksort's partition is in-place, yet the sort can use O(N) space. Reconcile that, then guarantee O(logN).
Hint: Count live frames, then control which call recurses.
Answer
Short answer: the recursion stack is auxiliary space, so quicksort is never in-place; recurse on the smaller partition first and loop on the larger to cap depth at log2N.
Why:Depth halving ➔ the explicit recursive call always at least halves the range. Without it, a degenerate split stacks N frames — the figure the sorting summary records for quicksort’s worst case ➔ Sorting Problem.
Bob pivots on the element closest to the mean. Worst case, and a family of inputs that triggers it?
Hint: The mean is a value; the pivot must be a rank.
Answer
Short answer:Θ(n2), on any sequence whose mean is far from its median — e.g. ai=i!.
Why:The mean is dragged by outliers, the median is not ➔ for factorials n1∑i!≥(n−1)!, so the closest element is the second-largest and the split is n−2 against 1; T(n)=T(n−2)+Θ(n) telescopes to Θ(n2) by the Arithmetic Series, whereas a 1:9fraction would still be Θ(nlogn). Constant-size splits, not merely unbalanced ones, are fatal.