Abstract
QuickSelect solves the Selection problem — finding the smallest element — by picking a random pivot at each step and recursing into only the one side that must contain the answer.
- Category: Divide and Conquer / Selection (Randomized)
- Input: A list of integers, and an integer with
- Output: The smallest element
- Paradigm: Randomized Divide and Conquer
- Typical use cases: median finding, order statistics, any single “find the ranked item” query
Core Logic (High-Level)
Recap of Selection’s partition-based strategy: pick a random pivot , split the list into (smaller than ), (equal to ), and (larger than ) using Partition with Pivot. Compare against and to determine which one group contains the smallest element, then recurse into only that group (adjusting if recursing into ).
Key Idea
Since we only ever recurse into one side — never both — the total work depends entirely on how unbalanced that one side is. Picking the pivot randomly doesn’t guarantee a balanced split on any single call, but on average it shrinks the problem fast enough to give linear expected time overall, even though individual unlucky calls can be bad.
Pseudocode (Mid-Level Implementation)
Algorithm 11 Quick Select
Input: List of integers and integer
Output: The smallest number in the set of integers
procedure QuickSelect()
if then
return
Pick a random integer in the list
Split the list into sets , ,
if then
return QuickSelect()
else if then
return
else
return QuickSelect()
Variables & Data Structures
| Name | Type | Purpose |
|---|---|---|
v | Integer | The randomly chosen pivot for this call |
SL, Sv, SR | Sublists | Elements smaller than, equal to, and greater than v, respectively — see Partition with Pivot |
k | Integer | The target rank — re-adjusted (`k - |
Helper Functions / Operations Used
- Partition with Pivot — splits the list around
vin time, extra space (in place). - Random pivot selection — pick
vuniformly at random from the current list; .
Proof of Correctness
Claim: QuickSelect(a, k) returns the true smallest element of a.
Proof (strong induction on ):
- Base case (): the only element is trivially the (and only) smallest — correct by inspection.
- Inductive hypothesis: assume
QuickSelectis correct on every list of size . - Inductive step: for a list of size , partitioning around
vproduces , , such that every element of is smaller than every element of , which is smaller than every element of . So:- If , the smallest overall is exactly the smallest within — correct by the inductive hypothesis, since .
- If , the smallest is one of the (equal-valued) elements of , i.e. itself — returned directly, correctly.
- If , the smallest overall is the smallest within — correct by the inductive hypothesis, since (as contains at least the pivot itself, so ).
Termination: every recursive call operates on a strictly smaller list ( or , since always contains at least the pivot), so the recursion depth is finite and the algorithm terminates.
Time & Space Complexity Analysis
Naive Best/Worst Case Reasoning
The runtime depends entirely on how big and turn out to be relative to — the recursive call costs or , plus for picking the pivot and partitioning.
Lucky case: if happens to land close to the median every time, , so no matter which side we recurse on:
By the Master Theorem (, so ): .
Unlucky case: if happens to be the max or min every time, (or ), so:
Expected Runtime (Rigorous)
Selecting the element uniformly at random splits the list into pieces of length and . Recursing on the relevant piece costs time proportional to .
The smallest possible max-size split is at :
and the worst case is at or :
If (a “good” pivot), then . Otherwise (a “bad” pivot), . Since a uniformly random pivot lands in the “good” range with probability , this gives an upper bound on the expected runtime:
\begin{align*} ET(n) &\leq \frac{1}{2}ET\left(\frac{3n}{4}\right) + \frac{1}{2}ET(n) + O(n) \ ET(n) &\leq ET\left(\frac{3n}{4}\right) + O(n) \end{align*}
Plugging into the Master Theorem with , , : since ,
General Case
| Complexity | Notes | |
|---|---|---|
| Time | expected, worst case | Randomized pivot choice makes the worst case extremely unlikely, but not impossible |
| Space | auxiliary if partitioning in place; expected recursion depth (worst case ) | Follows directly from the same lucky/unlucky split analysis above, applied to call-stack depth instead of time |
Best / Worst / Average Case
- Best case: — even a single lucky partition near the median-heavy path keeps total work linear (geometric decay: ).
- Worst case: — pivot is repeatedly the min or max (e.g. an adversarially chosen or already-sorted input paired with an unlucky random draw every time).
- Average / Expected case: — proven rigorously above via the “good pivot” probability argument.
Drawbacks / Constraints
- worst case is real, if rare. Randomization makes an adversary unable to force bad performance deterministically, but doesn’t eliminate the possibility — pathologically unlucky random draws can still occur.
- Not suitable for: situations requiring a guaranteed worst-case bound (e.g. real-time systems where a single slow call is unacceptable) — see Deterministic Selection for a pivot-selection strategy that guarantees worst case, at the cost of a larger constant factor.
- Not suitable for: repeated queries for many different on the same list — see Selection’s Drawbacks for why sorting once can be better in that case.