Counting Sort
Last updated
Counting sort is a non-comparison sort for integers in a known, limited range. It counts how many times each value appears, then uses those counts to write every value directly into its sorted position - no comparisons needed. Press play above to watch the values get tallied and then placed back in order.
Counting sort runs in O(n + k) time, where k is the range of the input values. When k is not much larger than n it is extremely fast and can beat O(n log n) comparison sorts, but if the value range is huge the O(k) count array makes it impractical.
Time & space complexity
| Case | Complexity | Notes |
|---|---|---|
| Time | O(n + k) | n elements, k = value range |
| Space | O(n + k) | Count array + output array |
| Stable | Yes | When placed right-to-left using prefix sums |
| Comparison? | No | Sorts by counting, not comparing |
| Best for | Small integer range | k close to n |
Step by step
| Step | What happens |
|---|---|
| 1 | Find the maximum value to size the count array. |
| 2 | Count how many times each value occurs. |
| 3 | (Optional) Convert counts to prefix sums for stability. |
| 4 | Write each value into the output the number of times it appears. |
| 5 | The output array is now fully sorted. |
Worked example
Sorting [1, 4, 1, 2, 4] (values range from 0 to 4, so the count array has 5 slots):
| Pass | State | Action |
|---|---|---|
| Scan input | count = [0, 2, 1, 0, 2] | Tally occurrences: 1 appears twice, 2 once, 4 twice. |
| Prefix sums | count = [0, 2, 3, 3, 5] | Each slot now holds how many values are <= its index, giving final positions. |
Place 4 | output = [_, _, _, _, 4] | Read right-to-left: count[4] = 5, so 4 goes to index 4; decrement to 4. |
Place 2 | output = [_, _, 2, _, 4] | count[2] = 3, so 2 goes to index 2; decrement to 2. |
Place 1 | output = [_, 1, 2, _, 4] | count[1] = 2, so 1 goes to index 1; decrement to 1. |
Place 4 | output = [_, 1, 2, 4, 4] | count[4] = 4, so this 4 goes to index 3; decrement to 3. |
Place 1 | output = [1, 1, 2, 4, 4] | count[1] = 1, so this 1 goes to index 0. Array is sorted. |
When to use counting sort
| Use it when | Avoid it when |
|---|---|
| You sort integers (or keys mappable to integers) in a small, known range. | The value range k is far larger than the element count n. |
You need linear O(n + k) time and can afford the extra arrays. | Memory is tight - the count array costs O(k) regardless of n. |
| You need a stable sort as a subroutine (e.g. inside radix sort). | Keys are floats, strings, or arbitrary objects with no integer mapping. |
| The maximum value is bounded and cheap to compute up front. | The range is unknown or unbounded, so you cannot size the count array. |
Counting Sort code
A clean, runnable Counting Sort implementation in Python, JavaScript, Java, C++, C. Pick a language, copy the code, or open it pre-loaded in the Coddy Playground.
Counting Sort code in Python
1def counting_sort(a):2 # Works for non-negative integers with a small max value3 counts = [0] * (max(a) + 1)4 for value in a:5 counts[value] += 16 # Prefix sums turn counts into final positions7 for i in range(1, len(counts)):8 counts[i] += counts[i - 1]9 out = [0] * len(a)10 for value in reversed(a): # reversed keeps equal values stable11 counts[value] -= 112 out[counts[value]] = value13 return out14
15
16nums = [4, 2, 2, 8, 3, 3, 1]17print("Before:", nums)18print("After: ", counting_sort(nums))Counting Sort code in JavaScript
1function countingSort(arr) {2 // Count occurrences of each value, then rebuild in order3 const max = Math.max(...arr);4 const count = new Array(max + 1).fill(0);5 for (const x of arr) count[x]++;6 const out = [];7 count.forEach((c, value) => {8 for (let k = 0; k < c; k++) out.push(value);9 });10 return out;11}12
13const data = [4, 2, 9, 2, 7, 4, 1, 4];14console.log("Before:", data);15console.log("Sorted:", countingSort(data));Counting Sort code in Java
1import java.util.Arrays;2
3public class Main {4 static int[] countingSort(int[] arr) {5 int max = 0;6 for (int v : arr) max = Math.max(max, v);7 int[] count = new int[max + 1];8 for (int v : arr) count[v]++;9 // Prefix sums turn counts into final positions10 for (int i = 1; i <= max; i++) count[i] += count[i - 1];11 int[] out = new int[arr.length];12 // Walk backwards so equal values keep their order (stable)13 for (int i = arr.length - 1; i >= 0; i--) {14 out[--count[arr[i]]] = arr[i];15 }16 return out;17 }18
19 public static void main(String[] args) {20 int[] arr = {4, 2, 2, 8, 3, 3, 1};21 System.out.println("Before: " + Arrays.toString(arr));22 int[] sorted = countingSort(arr);23 System.out.println("After: " + Arrays.toString(sorted));24 }25}Counting Sort code in C++
1#include <algorithm>2#include <iostream>3#include <vector>4
5void printVec(const std::vector<int>& a) {6 for (int x : a) std::cout << x << " ";7 std::cout << "\n";8}9
10void countingSort(std::vector<int>& a) {11 if (a.empty()) return;12 int maxVal = *std::max_element(a.begin(), a.end());13 // count[v] = how many times v appears14 std::vector<int> count(maxVal + 1, 0);15 for (int x : a) ++count[x];16 // Rebuild the array from the counts17 size_t idx = 0;18 for (int v = 0; v <= maxVal; ++v) {19 while (count[v]-- > 0) a[idx++] = v;20 }21}22
23int main() {24 std::vector<int> data = {4, 2, 2, 8, 3, 3, 1, 7};25 std::cout << "Before: ";26 printVec(data);27 countingSort(data);28 std::cout << "After: ";29 printVec(data);30 return 0;31}Counting Sort code in C
1#include <stdio.h>2#include <stdlib.h>3
4void printArr(const int a[], int n) {5 for (int i = 0; i < n; i++) printf("%d ", a[i]);6 printf("\n");7}8
9void countingSort(int a[], int n) {10 int maxVal = a[0];11 for (int i = 1; i < n; i++) {12 if (a[i] > maxVal) maxVal = a[i];13 }14 // count[v] = how many times v appears15 int* count = calloc(maxVal + 1, sizeof(int));16 for (int i = 0; i < n; i++) count[a[i]]++;17 // Rebuild the array from the counts18 int idx = 0;19 for (int v = 0; v <= maxVal; v++) {20 while (count[v]-- > 0) a[idx++] = v;21 }22 free(count);23}24
25int main(void) {26 int data[] = {4, 2, 2, 8, 3, 3, 1, 7};27 int n = sizeof(data) / sizeof(data[0]);28 printf("Before: ");29 printArr(data, n);30 countingSort(data, n);31 printf("After: ");32 printArr(data, n);33 return 0;34}Counting Sort FAQ
What is the time complexity of counting sort?
O(n + k), where n is the number of elements and k is the range of possible values. When k = O(n) this is linear time. It uses O(n + k) extra space.Is counting sort stable?
It can be. The stable version builds prefix sums of the counts and places elements from right to left, which preserves the relative order of equal keys. The simple "rewrite by value" version shown here produces a correct sort but is used mainly for plain integers.
When should I use counting sort?
k is much larger than the number of elements, the count array wastes memory and a comparison sort is better.What is the difference between counting sort and radix sort?
10 for decimal digits). Radix sort handles large value ranges that would make a single counting sort impractical.Why is counting sort not always faster than quicksort?
O(n + k), so it only wins when the value range k is comparable to n. If k is huge - say sorting 100 values in the range 0 to 1,000,000,000 - the O(k) count array dominates and wastes memory, while an O(n log n) comparison sort like quicksort stays fast and space-efficient.Can counting sort handle negative numbers?
value - min, so the smallest value maps to index 0. The count array size becomes max - min + 1. Forgetting this offset is a common bug that crashes on negative inputs.