Don't compare — tally each value's count, turn the tallies into positions, and place every item directly into its slot. O(n + k).
Counting sort never compares two values. Instead it tallies how many times each possible value appears, converts those tallies into running positions, and drops every item straight into its final slot. Because it sidesteps comparisons entirely, it beats the O(n log n) comparison lower bound — but only when the values come from a small range k.
count[] table of size k.count[v] becomes the number of items ≤ v — i.e. where v's block ends in the output.count[v], and write each item to that index in the output.function countingSort(arr, k) { // values in 0..k-1
const count = new Array(k).fill(0);
for (const v of arr) count[v]++; // tally
for (let i = 1; i < k; i++) count[i] += count[i - 1]; // prefix sums
const out = new Array(arr.length);
for (let i = arr.length - 1; i >= 0; i--) { // right to left = stable
out[--count[arr[i]]] = arr[i];
}
return out;
}k, the size of the value range, not with n. Sorting a handful of numbers up to a billion would need a billion-slot count array — useless. Counting sort shines only when k is comparable to n (small integers, ages, letters).