Skip to main content
Linear-Time Sorts

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.

O(d * (n + k))
·
O(n + k)

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

Radix sort: sort by ones digit first
170
0
90
1
802
2
2
3
24
4
45
5
75
6
66
7
By ones0:170,90 | 2:802,2 | 4:24 | 5:45,75 | 6:66
1/3

Code

Java
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

1Sort by least significant digit first, then next, etc.
2Each digit sort must be stable (counting sort works)
3d = number of digits, k = base (usually 10)

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.

Key insight

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.