Dutch National Flag Three Way Partition in DSA Rust - Time & Space Complexity
We want to understand how the time needed to sort an array into three parts grows as the array gets bigger.
Specifically, how fast can we separate values less than, equal to, and greater than a pivot?
Analyze the time complexity of the following code snippet.
fn dutch_national_flag(arr: &mut [i32], pivot: i32) {
let mut low = 0;
let mut mid = 0;
let mut high = arr.len().saturating_sub(1);
while mid <= high {
if arr[mid] < pivot {
arr.swap(low, mid);
low += 1;
mid += 1;
} else if arr[mid] == pivot {
mid += 1;
} else {
arr.swap(mid, high);
if high == 0 { break; } // prevent underflow
high -= 1;
}
}
}
This code rearranges the array so that all elements less than the pivot come first, then equal elements, then greater elements.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The while loop that moves through the array with the mid pointer.
- How many times: Each element is visited at most once by mid, so up to n times where n is array length.
As the array size grows, the number of steps grows roughly the same as the number of elements.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 steps |
| 100 | About 100 steps |
| 1000 | About 1000 steps |
Pattern observation: The steps increase linearly with input size.
Time Complexity: O(n)
This means the time to complete the partition grows directly in proportion to the number of elements.
[X] Wrong: "Because there are nested if-else checks inside the loop, the time complexity is O(n²)."
[OK] Correct: The loop runs at most n times, and each step does only a few constant checks and swaps, so the total work is still proportional to n, not n squared.
Understanding this linear-time partitioning is a great skill for sorting and searching problems, showing you can handle multiple categories efficiently in one pass.
"What if we used two separate passes to partition instead of one? How would the time complexity change?"
Practice
Solution
Step 1: Understand the problem goal
The algorithm divides the array into three parts: less than pivot, equal to pivot, and greater than pivot.Step 2: Compare with other options
Sorting or finding max are different tasks; reversing is unrelated.Final Answer:
To rearrange an array into three parts based on a pivot value -> Option DQuick Check:
Partitioning by pivot = rearrange into three parts [OK]
- Confusing partition with full sorting
- Thinking it finds max or min values
- Assuming it reverses the array
Solution
Step 1: Identify mutability requirement
Indices must be mutable to update during partitioning.Step 2: Check each declaration
Only let mut low = 0; let mut mid = 0; let mut high = arr.len() - 1; declares all three indices as mutable.Final Answer:
let mut low = 0; let mut mid = 0; let mut high = arr.len() - 1; -> Option AQuick Check:
All indices mutable = correct declaration [OK]
- Forgetting 'mut' keyword for variables that change
- Mixing mutable and immutable declarations incorrectly
- Using immutable variables causing compile errors
let mut arr = vec![2, 0, 2, 1, 1, 0]; let pivot = 1; // After partitioning // arr = ?
Solution
Step 1: Understand partitioning by pivot 1
Elements less than 1 go first (0s), then equal to 1, then greater than 1 (2s).Step 2: Rearrange array accordingly
Original: [2, 0, 2, 1, 1, 0] After partition: [0, 0, 1, 1, 2, 2]Final Answer:
[0, 0, 1, 1, 2, 2] -> Option BQuick Check:
Partitioned array = [0, 0, 1, 1, 2, 2] [OK]
- Not grouping equal elements in the middle
- Mixing order of less and greater groups
- Assuming full sorting instead of partitioning
let mut low = 0;
let mut mid = 0;
let mut high = arr.len() - 1;
while mid <= high {
if arr[mid] < pivot {
arr.swap(low, mid);
low += 1;
mid += 1;
} else if arr[mid] == pivot {
mid += 1;
} else {
arr.swap(mid, high);
high -= 1;
}
}Solution
Step 1: Analyze pointer updates after swaps
When swapping arr[low] and arr[mid], mid must also move forward to avoid infinite loop.Step 2: Identify missing mid increment
Code increments mid only when arr[mid] == pivot, but not after swapping with low.Final Answer:
Missing increment of mid after swapping with low -> Option CQuick Check:
mid must increment after swap with low to progress [OK]
- Forgetting to increment mid after swap with low
- Changing mid incorrectly in else block
- Misunderstanding pointer movements
Solution
Step 1: Understand the Dutch National Flag approach
It uses three pointers to partition the array into three parts efficiently in one pass.Step 2: Compare with other methods
Built-in sort or counting are valid but not the Dutch National Flag algorithm; two pointers are insufficient for three groups.Final Answer:
Use three pointers low, mid, high; move mid forward, swap with low if 0, swap with high if 2. -> Option AQuick Check:
Three pointers and swaps = Dutch National Flag method [OK]
- Using sorting instead of partitioning
- Trying two pointers for three groups
- Ignoring efficient one-pass solution
Ready to prove it?
Pass the test and this pattern moves unknown
