Skip to content

Counting Sort with Negative Keys

Extend counting sort to handle negative integers by shifting keys into a nonnegative index range.

Counting sort normally assumes keys lie in a nonnegative range. This variant handles negative integers by shifting all values so that the minimum becomes zero, then applying standard counting sort.

Problem

Given an array AA of nn integers that may include negative values, sort the array.

Let:

min=min(A),max=max(A) \min = \min(A),\quad \max = \max(A)

Idea

Shift every value by min-\min so all keys become nonnegative:

x=xmin x' = x - \min

Then apply counting sort on xx' in range [0,maxmin][0, \max - \min], and map back if needed.

Algorithm

counting_sort_with_negatives(A):
    lo = minimum(A)
    hi = maximum(A)
    k = hi - lo + 1

    count = [0] * k

    for x in A:
        count[x - lo] += 1

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

    return A

Example

Let:

A=[3,1,2,0,2,1] A = [-3, -1, -2, 0, 2, 1]

Shift:

lo=3 lo = -3

Mapped values:

[0,2,1,3,5,4] [0, 2, 1, 3, 5, 4]

After sorting and shifting back:

[3,2,1,0,1,2] [-3, -2, -1, 0, 1, 2]

Correctness

The transformation x=xminx' = x - \min is a bijection between the original values and the shifted values. It preserves order:

x1<x2    x1<x2 x_1 < x_2 \iff x_1' < x_2'

Counting sort correctly orders the shifted values, so mapping back yields the correct sorted order of the original values.

Complexity

Let:

  • nn be the number of elements
  • k=maxmin+1k = \max - \min + 1 be the range size

Time:

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

Space:

O(k) O(k)

Properties

propertyvalue
stableyes, if using stable variant
in placeno
comparison basedno
supports negativesyes

When to Use

Use this variant when:

  • keys include negative integers
  • the value range is small
  • linear-time sorting is desired

Avoid when the range kk is large compared to nn, since memory usage becomes inefficient.

Implementation

def counting_sort_with_negatives(a):
    if not a:
        return a

    lo = min(a)
    hi = max(a)
    k = hi - lo + 1

    count = [0] * k

    for x in a:
        count[x - lo] += 1

    i = 0
    for v in range(k):
        while count[v] > 0:
            a[i] = v + lo
            i += 1
            count[v] -= 1

    return a