Skip to content

Counting Sort

Sort integers by counting occurrences of each key and reconstructing the output in linear time.

Counting sort is a non-comparison sorting algorithm for integer keys within a bounded range. It counts how many times each value appears, then reconstructs the sorted order using these counts.

It runs in linear time when the key range is not significantly larger than the number of elements.

Problem

Given an array AA of nn integers where each value lies in a range [0,k][0, k], produce a sorted array.

Idea

Instead of comparing elements, count how many times each value appears.

Let:

  • C[i]C[i] be the number of elements equal to ii
  • Then expand counts to reconstruct the sorted sequence

For stable sorting, use prefix sums to compute positions.

Algorithm (basic version)

counting_sort(A, k):
    C = array of size k+1 filled with 0

    for x in A:
        C[x] += 1

    i = 0
    for v from 0 to k:
        while C[v] > 0:
            A[i] = v
            i += 1
            C[v] -= 1

Stable Version

To preserve order of equal elements:

  1. Count frequencies
  2. Compute prefix sums
  3. place elements into output array in reverse order
counting_sort_stable(A, k):
    C = [0] * (k + 1)

    for x in A:
        C[x] += 1

    for i in range(1, k + 1):
        C[i] += C[i - 1]

    B = [0] * len(A)

    for i in range(len(A) - 1, -1, -1):
        x = A[i]
        C[x] -= 1
        B[C[x]] = x

    return B

Example

Let:

A=[4,2,2,8,3,3,1] A = [4, 2, 2, 8, 3, 3, 1]

Counts:

valuecount
11
22
32
41
81

Reconstructed sorted array:

[1,2,2,3,3,4,8] [1, 2, 2, 3, 3, 4, 8]

Correctness

Each element contributes exactly one count to its key bucket. The reconstruction step outputs exactly that many copies of each key in increasing order, so the result is sorted.

In the stable version, prefix sums map each occurrence to a unique final index, preserving relative order.

Complexity

componentcost
countingO(n)O(n)
prefix sumO(k)O(k)
reconstructionO(n)O(n)
totalO(n+k)O(n + k)

Space:

O(n+k) O(n + k)

Constraints

Counting sort is efficient when:

k=O(n) k = O(n)

If knk \gg n, memory and time become inefficient.

When to Use

Use counting sort when:

  • keys are integers in a small range
  • stability is required
  • linear time is needed
  • comparison sorting overhead is too high

It is often used as a building block in radix sort.

Implementation (Go)

func CountingSort(a []int, k int) []int {
    count := make([]int, k+1)

    for _, v := range a {
        count[v]++
    }

    result := make([]int, len(a))
    idx := 0

    for v := 0; v <= k; v++ {
        for count[v] > 0 {
            result[idx] = v
            idx++
            count[v]--
        }
    }

    return result
}