Radix Sort Algorithm in DSA Rust - Time & Space Complexity
We want to understand how the time taken by Radix Sort changes as the input size grows.
Specifically, how the number of steps depends on the number of items and their digit length.
Analyze the time complexity of the following Radix Sort code snippet.
fn radix_sort(arr: &mut [u32]) {
let max = *arr.iter().max().unwrap_or(&0);
let mut exp = 1;
while max / exp > 0 {
counting_sort_by_digit(arr, exp);
exp *= 10;
}
}
fn counting_sort_by_digit(arr: &mut [u32], exp: u32) {
let mut output = vec![0; arr.len()];
let mut count = vec![0; 10];
for &num in arr.iter() {
count[((num / exp) % 10) as usize] += 1;
}
for i in 1..10 {
count[i] += count[i - 1];
}
for &num in arr.iter().rev() {
let idx = ((num / exp) % 10) as usize;
count[idx] -= 1;
output[count[idx]] = num;
}
arr.copy_from_slice(&output);
}
This code sorts numbers by processing each digit from least to most significant using counting sort.
Look for loops and repeated steps.
- Primary operation: Counting sort runs once per digit place.
- How many times: Number of digits in the largest number (d times).
- Inside counting sort, we loop over all n elements multiple times.
For each digit, we do a counting sort over all n items.
| Input Size (n) | Approx. Operations (d * n) |
|---|---|
| 10 | 10 * d |
| 100 | 100 * d |
| 1000 | 1000 * d |
Pattern observation: The time grows linearly with the number of items and also linearly with the number of digits.
Time Complexity: O(d * n)
This means the time grows linearly with the number of items and the number of digits in the largest number.
[X] Wrong: "Radix sort is always faster than comparison sorts like quicksort because it doesn't compare elements."
[OK] Correct: Radix sort depends on the number of digits (d). If d is large, it can be slower than efficient comparison sorts which are O(n log n). So it's not always faster.
Understanding Radix Sort's time complexity helps you explain when it's a good choice and shows you can analyze algorithms beyond simple comparisons.
"What if the numbers were very large with many digits? How would that affect the time complexity?"
Practice
Radix Sort Algorithm?Solution
Step 1: Understand Radix Sort approach
Radix sort sorts numbers by processing each digit separately, starting from the least significant digit (rightmost).Step 2: Compare with other sorting methods
Unlike comparison-based sorts, radix sort uses digit positions to sort without direct element comparisons.Final Answer:
Sort numbers digit by digit starting from the least significant digit -> Option DQuick Check:
Radix sort = digit-by-digit sorting [OK]
- Thinking radix sort compares elements directly
- Assuming it sorts by dividing arrays recursively
- Confusing it with bubble or quick sort methods
Solution
Step 1: Understand bucket structure needed
Radix sort uses buckets as vectors of vectors to hold numbers for each digit (0-9).Step 2: Check Rust syntax for initializing vector of vectors
Usingvec![Vec::new(); 10]creates 10 empty vectors, one for each digit bucket.Final Answer:
let mut buckets: Vec = vec![Vec::new(); 10]; -> Option AQuick Check:
Vector of vectors for buckets = let mut buckets: Vec = vec![Vec::new(); 10]; [OK]
- Using Vec<i32> instead of Vec for buckets
- Using with_capacity without initializing inner vectors
- Initializing buckets as integers instead of vectors
let arr = vec![170, 45, 75, 90, 802, 24, 2, 66];
let mut buckets: Vec = vec![Vec::new(); 10];
for &num in &arr {
let digit = num % 10;
buckets[digit as usize].push(num);
}
let mut result = Vec::new();
for bucket in buckets {
for num in bucket {
result.push(num);
}
}
println!("{:?}", result);Solution
Step 1: Calculate least significant digit for each number
Digits: 170%10=0, 45%10=5, 75%10=5, 90%10=0, 802%10=2, 24%10=4, 2%10=2, 66%10=6.Step 2: Place numbers in buckets and flatten
Buckets: 0->[170,90], 2->[802,2], 4->[24], 5->[45,75], 6->[66]. Flattening in order: [170, 90, 802, 2, 24, 45, 75, 66].Final Answer:
[170, 90, 802, 2, 24, 45, 75, 66] -> Option BQuick Check:
Sorted by least digit = [170, 90, 802, 2, 24, 45, 75, 66] [OK]
- Mixing up digit extraction with division
- Not preserving order within buckets
- Incorrectly flattening buckets
let arr = vec![170, 45, 75];
let mut buckets: Vec = vec![Vec::new(); 10];
for num in arr {
let digit = num / 10 % 10;
buckets[digit].push(num);
}Solution
Step 1: Identify type mismatch in indexing
Variabledigitis an integer but Rust requires usize for vector indexing.Step 2: Fix by casting digit to usize
Usebuckets[digit as usize]to correctly index the vector.Final Answer:
Changebuckets[digit]tobuckets[digit as usize]-> Option AQuick Check:
Vector index must be usize = Changebuckets[digit]tobuckets[digit as usize][OK]
- Using integer directly as vector index without casting
- Changing digit calculation unnecessarily
- Incorrect bucket initialization
fn radix_sort(mut arr: Vec<i32>) -> Vec<i32> {
let max = *arr.iter().max().unwrap();
let mut exp = 1;
while max / exp > 0 {
let mut buckets: Vec = vec![Vec::new(); 10];
for &num in &arr {
let digit = (num / exp) % 10;
buckets[digit as usize].push(num);
}
arr.clear();
for bucket in buckets {
for num in bucket {
arr.push(num);
}
}
exp *= 10;
}
arr
}
let input = vec![329, 457, 657, 839, 436, 720, 355];
let sorted = radix_sort(input);
println!("{:?}", sorted);Solution
Step 1: Understand the radix sort passes
The function sorts by digits starting from least significant (units), then tens, then hundreds until max digit processed.Step 2: Trace sorting steps on input
After all passes, the vector is sorted ascending: [329, 355, 436, 457, 657, 720, 839].Final Answer:
[329, 355, 436, 457, 657, 720, 839] -> Option CQuick Check:
Radix sort final output = sorted ascending [OK]
- Confusing order as descending
- Missing clearing array before collecting buckets
- Not multiplying exp by 10 each iteration
Ready to prove it?
Pass the test and this pattern moves unknown
