Next Permutation of Array in DSA Rust - Time & Space Complexity
We want to understand how the time needed to find the next permutation changes as the array size grows.
Specifically, how many steps does the algorithm take when the array gets bigger?
Analyze the time complexity of the following code snippet.
fn next_permutation(nums: &mut [i32]) {
let n = nums.len();
if n < 2 { return; }
let mut i = n - 2;
while i != usize::MAX && nums[i] >= nums[i + 1] {
i = i.wrapping_sub(1);
}
if i != usize::MAX {
let mut j = n - 1;
while nums[j] <= nums[i] {
j -= 1;
}
nums.swap(i, j);
}
nums[i + 1..].reverse();
}
This code finds the next lexicographical permutation of the array in place.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Two while loops scanning parts of the array and one reverse operation on a subarray.
- How many times: Each loop runs at most n times, where n is the array length.
As the array size grows, the loops and reverse operation may scan larger parts of the array.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | Up to about 30 steps |
| 100 | Up to about 300 steps |
| 1000 | Up to about 3000 steps |
Pattern observation: The number of steps grows roughly in direct proportion to the array size.
Time Complexity: O(n)
This means the time to find the next permutation grows linearly with the size of the array.
[X] Wrong: "The algorithm always scans the entire array multiple times, so it must be slower than linear."
[OK] Correct: Each loop scans only part of the array and they do not nest, so total work is proportional to the array size, not more.
Understanding this linear time complexity helps you explain how efficient your solution is and shows you can analyze algorithms that work with arrays in place.
"What if we changed the array to a linked list? How would the time complexity of finding the next permutation change?"
Practice
next_permutation algorithm do to an array of numbers?Solution
Step 1: Understand the purpose of next_permutation
The algorithm finds the next arrangement of elements that is just larger than the current one in dictionary order.Step 2: Compare with other options
Sorting or reversing changes order but does not guarantee the next lexicographical permutation. Finding max element is unrelated.Final Answer:
It rearranges the array to the next lexicographically greater permutation. -> Option AQuick Check:
Next permutation = next lexicographically greater order [OK]
- Confusing next permutation with sorting
- Thinking it reverses the array always
- Assuming it finds max element
nums at indices i and j?Solution
Step 1: Recall Rust vector swap method
Rust's standard Vec<T> has a methodswap(i, j)to exchange elements at indices i and j.Step 2: Check other options for correctness
nums[i] = nums[j]; nums[j] = nums[i]; incorrectly assigns values without temporary storage, causing wrong swap. nums.swap_elements(i, j); uses a non-existent method. nums.swap(i, j) -> (); has invalid syntax.Final Answer:
nums.swap(i, j); -> Option CQuick Check:
Correct swap method = nums.swap(i, j) [OK]
- Assigning without temp variable causing overwrite
- Using non-existent methods
- Incorrect syntax with arrows or extra symbols
nums = vec![1, 3, 2]?
let mut nums = vec![1, 3, 2];
if next_permutation(&mut nums) {
println!("{:?}", nums);
} else {
println!("No next permutation");
}
fn next_permutation(nums: &mut Vec<i32>) -> bool {
let n = nums.len();
if n < 2 { return false; }
let mut i = n - 2;
while i != usize::MAX && nums[i] >= nums[i + 1] {
if i == 0 { break; }
i -= 1;
}
if i == usize::MAX || nums[i] >= nums[i + 1] {
nums.reverse();
return false;
}
let mut j = n - 1;
while nums[j] <= nums[i] {
j -= 1;
}
nums.swap(i, j);
nums[i + 1..].reverse();
true
}Solution
Step 1: Identify pivot index i
Starting from right, find i where nums[i] < nums[i+1]. For [1,3,2], i=0 because 1 < 3.Step 2: Find j to swap with i
From right, find j where nums[j] > nums[i]. Here j=2 (value 2 > 1).Step 3: Swap and reverse suffix
Swap nums[0] and nums[2]: [2,3,1]. Then reverse suffix after i: reverse [3,1] to [1,3]. Result: [2,1,3].Step 4: Check code logic carefully
Code breaks loop early if i=0 and condition met, so i=0 is pivot. But code returns false and reverses if no pivot found. Here pivot found, so returns true and prints new nums.Final Answer:
[2, 1, 3] -> Option AQuick Check:
Next permutation of [1,3,2] = [2,1,3] [OK]
- Not reversing suffix after swap
- Wrong pivot index calculation
- Confusing when to return false
fn next_permutation(nums: &mut Vec<i32>) -> bool {
let n = nums.len();
if n < 2 { return false; }
let mut i = n - 2;
while nums[i] >= nums[i + 1] {
i -= 1;
}
if nums[i] >= nums[i + 1] {
nums.reverse();
return false;
}
let mut j = n - 1;
while nums[j] <= nums[i] {
j -= 1;
}
nums.swap(i, j);
nums[i + 1..].reverse();
true
}Solution
Step 1: Analyze the while loop condition
The loop useswhile nums[i] >= nums[i + 1]and decrements i. When i reaches 0 and condition holds, next decrement causes underflow (usize wraps to large number).Step 2: Check consequences
This causes panic or incorrect behavior. The correct approach is to usei != usize::MAXor check before decrementing to avoid underflow.Final Answer:
The loop misses checking when i == 0, causing panic on underflow. -> Option BQuick Check:
Loop underflow bug = missing i == 0 check [OK]
- Ignoring unsigned integer underflow
- Incorrect swap usage
- Forgetting to reverse suffix
nums = vec![3, 2, 1], which is the highest permutation, what will be the state of nums after applying the next permutation function that returns false when no next permutation exists?Solution
Step 1: Identify if next permutation exists
For [3, 2, 1], the array is in descending order, which is the highest permutation. No next permutation exists.Step 2: Apply algorithm behavior when no next permutation
The algorithm reverses the entire array to the lowest permutation and returns false.Final Answer:
[1, 2, 3] -> Option DQuick Check:
Highest permutation reversed = lowest permutation [OK]
- Expecting no change when no next permutation
- Returning empty vector incorrectly
- Confusing highest and lowest permutations
Ready to prove it?
Pass the test and this pattern moves unknown
