Skip to main content
Algorithms Analysis
CHAPTER 18 Beginner

Counting Sort and Radix Sort

Updated: May 17, 2026
15 min read

# CHAPTER 18

Counting Sort and Radix Sort

1. Introduction

Every sorting algorithm we have studied so far (Bubble, Insertion, Merge, Quick, Heap) relies on asking a Boolean question: *"Is A greater than B?"* In 1956, computer scientists proved mathematically that any algorithm relying on comparisons (<, >) cannot physically execute faster than $O(N \log N)$. It is the absolute speed limit of the universe. However, there is a loophole. What if we do not compare the numbers? What if we just count them? Counting Sort and Radix Sort are highly specialized Non-Comparison algorithms. By completely abandoning if (A > B) logic, they shatter the speed limit, executing in blistering $O(N)$ Linear Time. The catch? They only work on raw, positive integers.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Explain the Non-Comparison algorithmic paradigm.
  • Trace the frequency array mechanism of Counting Sort.
  • Trace the digit-by-digit bucket mechanism of Radix Sort.
  • Analyze the severe $O(K)$ Space Complexity tradeoffs.
  • Identify when to use Radix Sort vs Quick Sort.

3. Counting Sort: The Execution Logic

Counting Sort is shockingly simple. It finds the highest number in the dataset, creates a brand new blank Array of that exact size, and then simply counts how many times each number appears!

The Mechanics: Array: [4, 2, 2, 8, 3, 3, 1]

  1. 1. Find Max: The highest number is 8.
  1. 2. Create Frequency Array: Create a blank array with indices exactly 0 through 8.
Counts = [0, 0, 0, 0, 0, 0, 0, 0, 0]
  1. 3. Tally Frequencies: Loop through the original data. Add +1 to the index matching the number.
Counts = [0, 1, 2, 2, 1, 0, 0, 0, 1] *(Translation: We found one '1', two '2's, two '3's, one '4', and one '8').*
  1. 4. Rebuild: Loop through the Counts array from left to right, rebuilding the sorted array directly from the frequencies!
Sorted = [1, 2, 2, 3, 3, 4, 8]

4. The Catastrophic Flaw of Counting Sort

Counting Sort is $O(N)$ fast. But look closely at Step 2. What if your dataset is [2, 1, 5, 99999999]? The highest number is 99 Million. Counting Sort is mathematically forced to allocate a massive blank array of 99 Million indices in RAM, just to sort 4 numbers! The server will violently crash with an OutOfMemoryError.

*Rule: Counting Sort is only viable when the absolute Maximum Value (K) in the dataset is small and heavily clustered.*

5. Radix Sort: The Savior

Radix Sort solves Counting Sort's memory nightmare. Instead of sorting the whole number at once, Radix Sort evaluates the integers digit by digit (usually starting from the least significant digit, the "1s place"). Because a single base-10 digit can only ever be 0 through 9, Radix Sort only requires exactly 10 Buckets in RAM, utterly eliminating the 99-Million array crash!

The Mechanics: Array: [170, 45, 75, 90, 802, 24, 2, 66]

  1. 1. Pass 1 (1s Place): Sort numbers strictly by their last digit.
[170, 90, 802, 2, 24, 45, 75, 66]
  1. 2. Pass 2 (10s Place): Sort numbers strictly by their middle digit. (Notice 802 and 2 act like 002).
[802, 2, 24, 45, 66, 170, 75, 90]
  1. 3. Pass 3 (100s Place): Sort numbers strictly by their first digit.
[2, 24, 45, 66, 75, 90, 170, 802] -> Perfectly Sorted!

6. Implementation in Code

java
123456789101112131415161718192021222324252627282930313233343536373839404142
// Java Example: Radix Sort
import java.util.*;

public class Radix {
    
    // The Execution Controller
    public static void radixSort(int[] arr) {
        int max = Arrays.stream(arr).max().getAsInt();
        
        // Execute Counting Sort digit-by-digit. (exp is 1, 10, 100...)
        for (int exp = 1; max / exp > 0; exp *= 10) {
            countingSortDigit(arr, exp);
        }
    }

    // The Inner Engine (A slightly modified Counting Sort)
    public static void countingSortDigit(int[] arr, int exp) {
        int n = arr.length;
        int[] output = new int[n];
        int[] count = new int[10]; // Radix Magic: We ONLY ever need 10 buckets!

        // Count frequencies based on the current isolated digit
        for (int i = 0; i < n; i++) {
            count[(arr[i] / exp) % 10]++;
        }

        // Calculate cumulative positions
        for (int i = 1; i < 10; i++) {
            count[i] += count[i - 1];
        }

        // Build the output array backwards to maintain Stability!
        for (int i = n - 1; i >= 0; i--) {
            int digit = (arr[i] / exp) % 10;
            output[count[digit] - 1] = arr[i];
            count[digit]--;
        }

        // Copy back to original
        System.arraycopy(output, 0, arr, 0, n);
    }
}

7. Complexity Analysis: True Linear Speed

Let $N$ be the number of elements. Let $K$ be the Maximum Value (for Counting Sort) or Number of Digits (for Radix Sort).
AlgorithmTime ComplexitySpace ComplexityDescription
Counting Sort$O(N + K)$$O(K)$Blazing fast, but causes fatal memory crashes if the highest number ($K$) is massively larger than $N$.
Radix Sort$O(N \times K)$$O(N)$Eliminates the $O(K)$ crash by isolating digits. $K$ becomes the maximum number of digits (e.g., 5 passes for 99,999).

8. Stability Classification

Radix Sort absolutely MANDATES Stability. Look at the passes in Section 5. During the 10s place pass, 802 and 2 both evaluate to 0. If the underlying digit-sorter is unstable, it will violently swap 802 and 2. This will completely obliterate the hard work accomplished by the 1s place pass! Because Radix builds organizational logic layer-by-layer, the underlying sorting engine must be perfectly Stable.

9. Real-World Applications

  • Big Data Analytics: If a supercomputer needs to sort 1 Billion integer IP Addresses or Zip Codes, Merge Sort ($O(N \log N)$) takes roughly 30 Billion operations. Radix Sort ($O(N \times K)$) takes roughly 5 Billion operations. At massive integer scales, Non-Comparison sorting saves phenomenal amounts of CPU time.

10. Common Mistakes

  • Applying to Strings or Floats: Junior developers hear "$O(N)$ speed" and try to Radix Sort an array of complex User Objects or negative floating-point decimals. The mathematical logic (number / exp % 10) shatters entirely on decimals and objects. Do not attempt this unless mapping strings explicitly to ASCII integer values.

11. Exercises

  1. 1. If your dataset contains negative numbers [-5, 2, -10, 8], why does the naive Counting Sort algorithm immediately throw an IndexOutOfBounds exception during Step 2?
  1. 2. How many full array iterations (Passes) does Radix Sort require to completely sort an array whose maximum value is 45,291?

12. MCQs with Answers

Question 1

What fundamental mathematical mechanism is strictly forbidden within the architecture of Counting Sort and Radix Sort?

Question 2

By successfully abandoning the constraints of Comparison-Based logic, what unprecedented Time Complexity scaling is unlocked by these algorithms?

Question 3

How does the Counting Sort algorithm dynamically map numbers into memory?

Question 4

What is the catastrophic vulnerability inherent to the naive Counting Sort architecture?

Question 5

How does Radix Sort elegantly bypass the catastrophic memory blowout of Counting Sort while retaining non-comparison speed?

Question 6

During the iterative execution of Radix Sort on the integer 4582, how many distinct sweeping passes must the overarching for loop execute to fully evaluate the element?

Question 7

What is the uncompromising functional requirement regarding Algorithmic Stability within the internal sub-routines of Radix Sort?

Question 8

What specific data-typing limitation heavily restricts the enterprise deployment of Counting and Radix Sort algorithms?

Question 9

If an enterprise server must sort 50 Million Zip Codes (which are perfectly structured 5-digit integers), what algorithm guarantees the absolute fastest execution?

Question 10

In the mathematical calculation for Counting Sort ($O(N + K)$), what variable does the integer $K$ explicitly define?

13. Interview Preparation

Top Interview Questions:
  • *Algorithmic Defense:* "If Radix Sort is mathematically $O(N)$ linear time, why does Python use Timsort ($O(N \log N)$) instead of Radix Sort as the default library engine?" *(Answer: Generalization! Standard libraries must be able to seamlessly sort Objects, Floats, and Strings using generalized comparison functions. Radix Sort is highly specialized and explicitly crashes on complex objects. Furthermore, if the integers are massive (e.g., 64-bit encryption keys), $K$ becomes huge, causing Radix's $O(N \times K)$ to actually run SLOWER than $O(N \log N)$!).*

14. Summary

Counting Sort and Radix Sort represent a brilliant paradigm shift. By refusing to answer the Boolean question of "Greater Than" or "Less Than", they exploit integer properties to achieve impossible mathematical velocities. They remind software architects that specialized, constrained algorithms can often outperform highly generalized enterprise solutions.

15. Next Chapter Recommendation

Sorting is complete. It is time to learn how to actively solve complex real-world logic problems. If you have 5 coins and need to make change for $0.99, how does the computer decide which coins to pick? In Chapter 19: Greedy Algorithms, we will explore the aggressive, short-sighted logic of immediate localized optimization.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·