The selection problem asks for one ranked element, whereas sorting asks for the complete order. This distinction lets quickselect discard work that cannot affect the requested rank. Counting sort and LSD radix sort go further: they can cross the comparison-sorting barrier by using structure in the keys, but only under explicit range and digit assumptions.
Motivation
Suppose a list contains millions of values and we need only its median. Sorting will answer the question, but the complete sorted order contains much more information than one median. A useful algorithmic habit is therefore to ask what output the problem actually requires before choosing a familiar routine.
The repository tutorial develops this idea in three stages. Full sorting gives a simple baseline. Partial selection sort stops after placing the first few order statistics. Quickselect reuses quicksort's partition operation but continues on only the side that can contain the target. The linear-time sorting lecture then changes the computational model: bounded integer keys can be counted, and multi-digit keys can be processed one stable digit at a time.
These algorithms solve a static, one-query problem. If many ranks will be queried without updates, sorting once may be reasonable. If insertions and deletions occur between queries, the dynamic-selection tutorial instead points toward a height-balanced search tree augmented with subtree sizes. Its logarithmic guarantee depends on maintaining balance and metadata, so that data-structure implementation belongs with the tree notes; here it serves only as a boundary between static selection and dynamic order statistics.
Definitions
Definition
Selection problem
Given a list of keys and an integer satisfying , return the kth smallest key. Rank is one-based, while array indices in pseudocode may be zero-based. Duplicate keys are counted with multiplicity: in , the first and second smallest keys are both .
The cases and are the minimum and maximum. Each needs a single scan, so selection cannot have a general lower bound of in the comparison model. The lower bound later in this note is about producing a complete sorted order, not about finding one rank.
Partial selection sort performs the first rounds of selection sort. In
round , it finds the minimum of the remaining suffix and swaps it into
position . It then returns A[k - 1]; it need not physically remove an
array element. Its exact number of key comparisons is
which is . It is linear when is a fixed constant, but quadratic when is proportional to .
Definition
Partition contract
For a current subarray of length , Partition returns an index , places
the chosen pivot at A[p], and guarantees that every index below contains
a key at most A[p], while every index above contains a key at least
A[p]. Thus the pivot value is a valid key of local rank , even when
equal keys occur. This final-pivot-index contract is stronger than a routine
that returns only a boundary between two regions.
With one-based rank relative to the current subarray, correct quickselect branching is:
Quickselect(A, m, k):
require 1 ≤ k ≤ m
if m == 1: return A[0]
p = Partition(A, m) // p is the pivot's final 0-based index
if k - 1 == p: return A[p]
if k - 1 is below p: return Quickselect(A[0:p], p, k)
return Quickselect(A[p+1:m], m-p-1, k-p-1)
The equality branch is essential. On the right, the new rank subtracts the left-side positions and the pivot itself.
At the start of every recursive call, the invariant is: the current subarray contains the original requested order statistic, and its parameter is that value's rank within this subarray. The left call preserves because no smaller positions have been discarded. The right call discards exactly positions, so it uses . The base case is reachable because an equality return stops at the pivot and either recursive branch is strictly shorter than its parent. A routine returning a Hoare-style boundary rather than the pivot's final index needs a different argument and must not be dropped into this pseudocode unchanged.
Randomized three-way quickselect
The source teaching trace above uses a two-way final-index partition. For the expected-time guarantee on inputs that may contain duplicates, use a separate three-way variant. Choose one current record uniformly at random as the pivot, then partition into strict-less block , equal block , and strict-greater block . With one-based local rank and , :
RandomizedQuickselect(A, m, k):
pivot = key of a uniformly random record in A
(L, E, G) = ThreeWayPartition(A, pivot)
if k ≤ |L|: return RandomizedQuickselect(L, |L|, k)
if k ≤ |L| + |E|: return pivot
return RandomizedQuickselect(G, |G|, k-|L|-|E|)
The same recursive-call invariant holds, but the discarded prefix on the greater branch now has size . Every recursive call uses a strict block, so it is shorter; if all keys are equal, is the whole input and the algorithm returns after one partition. This three-way contract is also different from a Hoare boundary and must be implemented and proved on its own terms.
Definition
Stable sorting
A sorting routine is stable if records with equal keys keep their relative input order in the output. Stability matters when a later pass sorts on one part of a compound key and must preserve order established by earlier passes.
Definition
Counting sort
For integer keys in the inclusive range , standard stable counting sort uses counters. It counts frequencies, converts them to prefix counts, and scans the input from right to left while placing records in a separate output array. Its time is and its auxiliary space is when both the output and count arrays are included. This standard stable version is not in-place.
After accumulation, C[x] is the number of records with key at most .
During right-to-left placement, --C[x] selects the last unused position in
key 's output block. The counters must be initialized to zero, and maximum
key means valid counters C[0] through C[K]: exactly cells.
Definition
LSD radix sort
Let every nonnegative key have digits in base . Least-significant-digit (LSD) radix sort stably sorts the whole array by digit , then digit , and continues through digit . If each pass is stable counting sort on digit values, the total time is and the auxiliary space is .
For -bit machine words grouped into -bit digits, and , so the cost is . Larger digits reduce passes but enlarge the counter array; smaller digits use compact counters but scan the array more times.
The word “linear” is therefore conditional. Counting sort is when . LSD radix sort is when the chosen representation makes constant and , for example fixed-width machine words with a suitable digit size. Negative keys, variable-length representations, or a huge key universe require additional handling rather than an unqualified linear-time claim.
Counting and LSD radix sort copy whole records while using a bounded integer or extracted digit for direct addressing. Stability is therefore about record identity, not visually indistinguishable equal numeric values.
Theorem/Proposition
Theorem
Why quickselect can avoid full sorting
Assume Partition satisfies the final-pivot-index contract. If its returned
index is , a target of local rank equals the pivot; a smaller target
rank lies in the left subarray; and a larger target rank lies in the right
subarray with adjusted rank . Consequently quickselect needs at most one
recursive call after each partition.
Theorem
Decision-tree lower bound for comparison sorting
For arbitrary inputs of distinct keys, every deterministic comparison-based sorting algorithm has a worst-case execution using comparisons. This statement assumes that key comparisons are the only way to learn their relative order; it does not apply unchanged when bounded integers can be used as array indices.
Theorem
Correctness of LSD radix sort
After completing stable passes on digits , the array is sorted by the -digit suffix viewed as a base- number. Hence, after all passes, the array is sorted by the complete key.
Proof sketch or proof idea
Quickselect branch correctness and cost
After partitioning, the pivot is in a position it could occupy in a completely sorted current subarray. Every position to its left contains a key no larger, and every position to its right contains a key no smaller. Therefore a target index below cannot require the right side, and a target index above cannot require the left side. Equality returns immediately. This proves the one-branch theorem; no assumption that either side is already internally sorted is needed.
Partitioning costs on a subproblem of size . If every pivot is extreme, the sizes are , giving . A perfectly balanced shrink gives the useful intuition , but that geometric series alone is not an average-case proof.
For the randomized three-way variant, assume each call chooses a record uniformly and independently from the current subarray and that comparisons and swaps take constant time. Give equal occurrences arbitrary consecutive ranks in sorted order. With probability at least , the chosen record's rank is in the middle half. Its strict-less and strict-greater blocks then both have size at most ; the target either returns from the equal block or survives in one of those strict blocks. The expected number of trials before such a shrink is at most two, and all partitions at that size scale cost in expectation. Summing over geometrically shrinking scales gives expected . The first partition costs in this model, so the expected time is . All-equal input takes one linear pass, while distinct-key extreme pivots still give a worst case.
Decision-tree lower-bound proof
For distinct arbitrary keys, all relative orders are possible. A deterministic comparison sort can be represented by a binary decision tree: each internal node compares two keys, and each leaf identifies the input permutation. Correctness requires at least leaves. A binary tree of height has at most leaves, so and . Let . The largest factors in are each at least , so
Thus some input follows a path of that length. Counting and radix sort do not contradict the result: they use digit extraction, arithmetic, and direct array addressing, and they restrict the key representation.
LSD radix invariant
The claim follows by induction on the passes. After digit , stability is irrelevant and the array is sorted by its last digit. Assume it is sorted by digits through . The next stable pass orders records by digit . Records with different digit- values are put in the correct order by that digit; records with equal digit- values retain their prior order, which by the induction hypothesis is the order of their lower-digit suffixes. The array is therefore sorted by digits through . After digit , that suffix is the whole key.
Worked examples
Worked example
Partial selection cost
For the tutorial array
, finding the fourth smallest key by
partial selection places , then , then , then into the first four
positions. With and , the four suffix scans make
comparisons, and A[3] is .
This is substantially less than all comparisons of a full selection sort on thirteen elements, but the advantage depends on small . For a median-scale rank, and the method becomes quadratic.
Worked example
Quickselect partition trace
Find the second smallest key in , using the tutorial's first-element pivots.
- Partition around to obtain . The pivot has index , or rank , so rank lies in the left subarray .
- Partition that subarray around . The pivot has local rank , so move right and adjust the target to .
- In , pivot has local rank . The equality branch returns .
The untouched partitions need not be sorted. The trace also shows why omitting the equality return or forgetting the right-side rank adjustment is a real correctness error.
Worked example
Counting sort from counts to stable placement
Let and . The six counters for keys through are
After prefix accumulation,
where counts keys at most . Scanning from right to left, place a
record of key at index --C'[x]. For example, the final input key sees
count , decrements it to , and occupies output index . Repeating this
operation produces
Right-to-left scanning matters when equal keys carry distinct records: the later equal record takes the later available output position, so their input order is preserved. The three phases cost , , and , hence overall.
Worked example
Why stability matters in radix sort
Apply base- LSD radix sort to :
- stable ones-digit pass: ;
- stable tens-digit pass: ;
- stable hundreds-digit pass: .
In the tens pass, for instance, remains before among keys with tens digit because their ones digits were already ordered. An unstable pass could reverse that pair and destroy the lower-digit ordering on which the induction proof depends.
Common mistakes
- Accepting or , or mixing one-based ranks with zero-based indices.
- Treating a partition boundary as though it were necessarily the pivot's final index.
- Omitting quickselect's equality return or failing to subtract when recursing right.
- Claiming quickselect is always linear, presenting balanced shrink as an average-case proof without a uniform randomized-pivot model, or omitting the three-way equal block when duplicates are allowed.
- Writing that sorting takes “at least ”; use for the comparison lower bound and state its assumptions.
- Allocating only counters for the inclusive key range , or forgetting to initialize all counters to zero.
- Calling the standard stable counting sort in-place, or scanning left to right while using decreasing prefix-count positions.
- Saying every radix-sort organization needs the same stable-pass argument. The theorem here is specifically for whole-array LSD radix sort.
- Quoting or dynamic-set operations without the required capacity, expected-hashing, or height-balance assumptions.
Summary
- Selection returns one order statistic; sorting returns all rank information.
- Partial selection costs and is attractive only when is small.
- The source two-way final-index trace lets quickselect recurse on one side. The duplicate-safe uniformly randomized three-way variant returns from its equal block and has expected time. All-equal input is ; worst case is .
- Comparison sorting of arbitrary distinct keys needs comparisons in the worst case by the decision-tree proof.
- Stable counting sort on keys uses counters, runs in , scans right to left for stability, and is not in-place in its standard output-array form.
- LSD radix sort with base- digits and stable digit passes runs in . Its linearity depends on the representation parameters.
Exercises
Checkpoint
Why is full sorting more work than selection?
Compare the requested output.
Solution · Answer
Selection asks for one ranked element. Sorting asks for the complete order of all elements, which contains more information than a single kth item.
Checkpoint
What extra assumption lets counting sort run in linear time?
Think about the count array.
Solution · Answer
The key range must be bounded so that the count array is not larger than a constant multiple of the input size; commonly this is stated as .
- Explain why quickselect recurses on only one partition side, including the equality case.
- Give a case where partial selection sort is reasonable, and a case where it is not.
- Explain why LSD radix sort needs a stable digit subroutine.
- For and , compute the exact comparison count of partial selection sort under the suffix-scan implementation.
- Starting from prefix counts , state where the rightmost key is placed and what its counter becomes.
- Explain precisely why counting sort and radix sort do not violate the comparison-sorting lower bound.
Solutions
Solution · Guided solutions
- Once the pivot's final index is known, the target rank is either the pivot, strictly left, or strictly right. Equality returns; only the relevant side can contain the remaining target.
- It is reasonable when is a small constant and only a few minimum-selection rounds are needed. It is poor for , such as a median, because its cost becomes quadratic.
- Stability preserves the ordering created by lower-digit passes among records tied on the current digit; without it, a later pass can scramble earlier digit information.
- The count is comparisons.
- The value is decremented to , so the record is placed at zero-based output index .
- The lower bound assumes arbitrary distinct keys and learns order only through comparisons. Counting and radix sort restrict key representations and also use arithmetic, digit extraction, and direct addressing.