V

Algorithm Visualizer

ZHEN
Share on WeiboShare on XGitHub repositoryAuthor website
Learning ToolsAlgorithm Complexity ReferenceAlgorithm Learning Paths
Data StructuresArrayLinked ListStackQueue and DequeBinary Search TreeBinary HeapHash TableGraphTrieDisjoint Set UnionLRU CacheSkip ListSegment TreeB+ TreeBloom FilterFenwick Tree
SortingBubble SortCocktail Shaker SortBitonic SortSelection SortInsertion SortBinary Insertion SortShell SortMerge SortTop-Down Merge SortQuick SortThree-Way Quick SortDual-Pivot Quick SortHeap SortCounting SortRadix SortBucket Sort
Graph AlgorithmsDijkstra's Shortest PathKruskal's Minimum Spanning TreePrim's Minimum Spanning TreeBellman-Ford Shortest PathsTopological SortFloyd-WarshallStrongly Connected Components2-SATMaximum FlowBipartite MatchingLowest Common AncestorEulerian Path
Dynamic ProgrammingEdit Distance0/1 KnapsackUnbounded KnapsackLongest Common SubsequenceLongest Increasing SubsequenceCoin ChangeStone MergingTraveling Salesperson DPTree Dynamic ProgrammingDigit DPRerooting DP
Backtracking and SearchN-QueensSubsetsPermutationsCombination SumMaze Solving with DFSNumber of IslandsWord SearchSudoku SolverA* Search
StringsKMP String MatchingRabin-Karp String MatchingBoyer-Moore String MatchingManacher's Longest Palindromic SubstringSuffix ArrayLCP ArrayAho-Corasick AutomatonZ Function
Math and Number TheorySieve of EratosthenesLinear SieveEuclidean AlgorithmBinary ExponentiationExtended Euclidean AlgorithmChinese Remainder TheoremEuler's Totient FunctionMiller-Rabin Primality TestFast Fourier TransformPollard's Rho Factorization
Computational GeometryConvex HullRotating CalipersClosest Pair of PointsLine Segment IntersectionBentley-Ottmann Sweep Line
SearchingBinary SearchLower and Upper BoundSearch in a Rotated Sorted ArrayBinary Search on the AnswerTernary Search

Counting Sort

Sorting compact integer ranges by counting instead of comparing

Replace comparisons with frequencies

When values are integers from a manageable range, use one bucket per value. The first pass counts every occurrence. The second pass walks buckets from smallest to largest and writes each value back as many times as it was counted.

Watch counts enter and leave buckets

The main array stays unchanged during counting while the bucket track grows. During write-back, the green pointer advances through the array and each active bucket decreases to zero. No pair of input elements is ever compared.

3
1
4
1
6
2
3
6
4
1
0
1
0
2
1
3
0
4
0
5
0
6

Read the next value 3 and increment its bucket to 1.

1function countingSort(a: number[]): number[] {
2 const min = Math.min(...a), max = Math.max(...a);
3 const count = new Array(max - min + 1).fill(0);
4 for (let i = 0; i < a.length; i++) count[a[i] - min]++;
5 let w = 0;
6 for (let v = 0; v < count.length; v++) {
7 while (count[v] > 0) {
8 a[w++] = v + min;
9 count[v]--;
10 }
11 }
12 return a;
13}
n10
min1
max6
k6
PhaseCount
i0
v-
w-
1 / 27

Range size is the real constraint

For n values spanning k distinct integer positions, time is O(n + k) and bucket space is O(k). The method is excellent when k is close to n, but wasteful for a huge sparse range. This direct write-back version does not preserve record order; a prefix-count output array can make it stable.

Counting Sort is a domain-specific optimization. Validate the value range before allocating buckets, especially when input is user-controlled.

Return to the learning paths to compare comparison and non-comparison sorting.