Radix Sort
Sort by one digit at a time, from least significant to most significant. Each digit sort uses counting sort (which is stable, preserving previous digit order). O(d·(n+k)) where d = number of digits.
How It Works
Radix sort orders integers by processing one digit position at a time, least significant first, using a stable sort — almost always counting sort — for each pass. Stability is the linchpin: when the pass for digit d finishes, ties on digit d retain the order established by all lower digits, so after the final, most significant pass the array is fully sorted.
With d digit positions and base k, the cost is O(d * (n + k)); choosing base 256 makes d small (four passes for 32-bit values) while keeping the per-pass count array tiny. For bounded-size integers d is a constant, so radix sort is effectively linear — beating comparison sorts asymptotically — at the price of O(n + k) auxiliary space and integer-like keys only. The MSD variant recurses from the most significant digit instead and suits variable-length strings.
Step-by-Step Visualization
Code
static int[] radixSort(int[] arr) {
int max = 0;
for (int x : arr) max = Math.max(max, x);
int[] result = arr.clone();
for (int exp = 1; max / exp > 0; exp *= 10) {
List<List<Integer>> buckets = new ArrayList<>();
for (int i = 0; i < 10; i++) buckets.add(new ArrayList<>());
for (int num : result) buckets.get((num / exp) % 10).add(num);
int idx = 0;
for (List<Integer> bucket : buckets)
for (int num : bucket) result[idx++] = num;
}
return result;
}Tips & Gotchas
Practice Problems
- 1Maximum Gap
- 2Sort an Array
- 3Query Kth Smallest Trimmed Number
About the Linear-Time Sorts Pattern
These bypass the O(n log n) barrier by NOT comparing elements. Instead, they use the values directly. The catch: they only work when values fall within a known, bounded range.
Sorting unlocks binary search, two-pointer, and greedy. Always ask: can I sort first? Custom comparators solve tricky ordering problems. Know QuickSelect for O(n) expected Kth element.
Common Sorting Interview Problems
- Sort Colors
- Kth Largest Element
- Merge Intervals
- Largest Number
- Sort List
- Meeting Rooms
Frequently Asked Questions
Why must radix sort go least-significant-digit first with a stable inner sort?
Each pass sorts on one digit while stability preserves the ordering created by all previous, lower-significance passes. By induction, after sorting on digit d the array is correctly ordered on the number formed by digits 0..d; an unstable inner sort would scramble those earlier results and break the invariant.
If radix sort is linear, why isn't it the default everywhere?
Its O(d*(n+k)) advantage only materializes when keys are fixed-width integers or strings and d stays small; it needs O(n+k) working memory, has weaker cache behavior across multiple full passes, and cannot handle arbitrary comparator-defined orderings. General-purpose libraries need comparator support, so they ship comparison sorts.
How do I radix sort negative numbers?
The digit passes treat bit patterns as unsigned, which would order negatives after positives. Either offset all values into a non-negative range first, or flip the sign bit before sorting and flip it back afterwards; for floats, a similar monotonic bit transformation exists.