Skip to content

Counting sort

Problem

Implement stable counting sort for integers, including negative integers.

Key trick

Translate each value by the minimum, convert counts into ending positions, and place input values from right to left.

The right-to-left placement makes the standard record-based version stable.

For linked lists, counting values and rebuilding nodes is possible, but this is usually less natural than merge sort.

Trap

Its complexity depends on \(k = \max(nums)-\min(nums)+1\); a huge range makes it impractical.

Why is it interesting?

It beats the comparison-sorting lower bound by exploiting bounded integer keys.

Python solution

class sort_counting_sort:
    def sort(self, nums: list[int]) -> list[int]:
        if not nums:
            return []

        lo = min(nums)
        hi = max(nums)

        # Offsetting by `lo` supports negative integers.
        counts = [0] * (hi - lo + 1)

        # Count occurrences of each value.
        for x in nums:
            counts[x - lo] += 1

        # Convert frequencies into cumulative ending positions.
        for i in range(1, len(counts)):
            counts[i] += counts[i - 1]

        res = [0] * len(nums)

        # Traverse right-to-left so equal records retain their relative order.
        for x in reversed(nums):
            idx = x - lo

            # Decrement first to obtain the zero-based output position.
            counts[idx] -= 1
            res[counts[idx]] = x

        return res