Sorting Algorithms
Counting & Bucket Sort
Non-comparison O(N) sorting for bounded integer ranges and uniform decimal distributions.
1. Introduction
What are Non-Comparison Sorts?
Non-Comparison Sorts are sorting algorithms that do not compare elements directly (like checkinga < b). Instead, they exploit properties of the data—such as integer range bounds or uniform distributions—to group and sort elements in linear O(N) time.
Why study them?
These algorithms bypass theO(N log N) lower bound of comparison-based sorting. By knowing their trade-offs, you can pick specialized algorithms that are vastly faster for specific constraints.
Where are they Used?
2. Mental Models
Counting Sort: Labeled Mail Slots
Imagine sorting a stack of 100 letters that only have integer ratings from0 to 5.
0 through 5.0, then slot 1, up to slot 5. The letters are now sorted!Bucket Sort: Sorting Mail by Zip Code
Imagine you need to sort letters for an entire state. You place several bins (buckets) representing ranges of zip codes (e.g.,90000-90999, 91000-91999).
3. Core Concepts & Implementations
Counting Sort
To ensure stability when sorting objects associated with integer keys, Counting Sort uses a prefix-sum array. This sum indicates the exact last index where each key belongs in the sorted array, allowing us to map elements from right-to-left.4. Visual Trace: Counting Sort
Let's stably sort [1, 4, 1, 2, 7, 5, 2] using Counting Sort.
1. Calculate Frequencies:
count = [0, 2, 2, 0, 1, 1, 0, 1] (indices 0 to 7)
2. Prefix Sum (Positions):
count = [0, 2, 4, 4, 5, 6, 6, 7]
3. Placing Stably (Right-to-Left):
- Element 2 at index 6: count[2] = 4. Output index 4 - 1 = 3. count[2] decrements to 3.
- Element 5 at index 5: count[5] = 6. Output index 6 - 1 = 5. count[5] decrements to 5.
- Element 7 at index 4: count[7] = 7. Output index 7 - 1 = 6. count[7] decrements to 6.
- Element 2 at index 3: count[2] = 3. Output index 3 - 1 = 2. count[2] decrements to 2.
- Element 1 at index 2: count[1] = 2. Output index 2 - 1 = 1. count[1] decrements to 1.
- Element 4 at index 1: count[4] = 5. Output index 5 - 1 = 4. count[4] decrements to 4.
- Element 1 at index 0: count[1] = 1. Output index 1 - 1 = 0. count[1] decrements to 0.
Sorted Output: [1, 1, 2, 2, 4, 5, 7]
5. Real-World Applications
L to be sorted in O(N × L) time.6. Interview Perspective
How Interviewers Ask This Topic
Interviewers verify whether you know the constraints of non-comparison sorts:[0..120]), making Counting Sort run in O(N) time, which is much faster than standard O(N log N) sorting for millions of people.Common Mistakes
[1, 999999999], your count array needs to allocate 1,000,000,000 integers, causing an Out of Memory (OOM) error! Only use Counting Sort when K (value range) is at most O(N).> 2. Implementing Unstable Counting Sort: Simply writing a frequency map and iterating 1..K printing elements ignores object properties, producing an unstable sort. Always write the full prefix-sum and output array mapping.
7. Summary
O(N + K) where K is the key range.8. Quiz
Question 1: Under what condition does Counting Sort run in linear O(N) time?
Answer: When the range of elementsK is less than or equal to the size of the array N (i.e., K = O(N)). If K \gg N, the complexity O(N + K) degrades, becoming dominated by K.
Question 2: Why is the prefix-sum array and right-to-left iteration necessary in Counting Sort?
Answer: They guarantee stability. Iterating the original array from right-to-left and decrementing prefix sum coordinates ensures that identical keys are placed into the output array in the exact same relative order they entered.Question 3: What is the average and worst-case time complexity of Bucket Sort?
Answer:O(N) when elements are uniformly distributed across buckets.O(N²) when all elements are distributed into a single bucket, forcing the algorithm to fallback to insertion sort on the entire array.Question 4: True or False: Non-comparison sorts violate the O(N log N) mathematical sorting lower bound.
Answer: False. TheO(N log N) lower bound only applies to comparison-based sorting. Non-comparison sorts use assumptions about the keys (like indexing buckets directly), which doesn't rely on binary decision tree comparison limits.
Question 5: How does Radix Sort sort integers of range [0..10^6] stably without allocating a size-10^6 array?
Answer: It sorts digit-by-digit (e.g., base 10 or base 256). For base 10, it makes\approx 6 passes of Counting Sort, each pass allocating a tiny size-10 count array. This achieves sorting in O(6 × N) \approx O(N) time with minimal memory overhead.