Generate All Permutations of Array in DSA C++ - Time & Space Complexity
When we generate all permutations of an array, we want to know how the time needed grows as the array gets bigger.
We ask: How many steps does it take to list every possible order of the array elements?
Analyze the time complexity of the following code snippet.
void permute(vector<int>& nums, int start, vector<vector<int>>& result) {
if (start == nums.size()) {
result.push_back(nums);
return;
}
for (int i = start; i < nums.size(); i++) {
swap(nums[start], nums[i]);
permute(nums, start + 1, result);
swap(nums[start], nums[i]);
}
}
This code generates all possible orders (permutations) of the array by swapping elements and exploring each choice recursively.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursive calls combined with a loop that swaps elements.
- How many times: For an array of size n, the function explores n choices at the first level, then n-1 at the next, and so on, leading to n! (factorial) total permutations.
Each time we add one more element, the number of permutations multiplies by that new size.
| Input Size (n) | Approx. Operations |
|---|---|
| 3 | 6 (3 x 2 x 1) |
| 5 | 120 (5 x 4 x 3 x 2 x 1) |
| 7 | 5040 (7 x 6 x 5 x 4 x 3 x 2 x 1) |
Pattern observation: The number of operations grows very fast, multiplying by the next number each time we add an element.
Time Complexity: O(n!)
This means the time needed grows very fast as the array size increases, because we must list every possible order.
[X] Wrong: "The time grows like n squared or n cubed because of the loops."
[OK] Correct: The loops are inside recursive calls that multiply the work, so the total grows much faster than simple loops.
Understanding this helps you explain why some problems take much longer as input grows, and shows you can analyze complex recursive code clearly.
"What if we only wanted permutations of length k from n elements? How would the time complexity change?"
Practice
Solution
Step 1: Understand permutations
Permutations are all possible ways to arrange elements in order.Step 2: Apply to array elements
Generating all permutations means listing every possible order of the array elements.Final Answer:
Listing all possible orders of the array elements -> Option AQuick Check:
Permutations = all orders [OK]
- Confusing permutations with sorting
- Thinking permutations remove duplicates
- Assuming permutations find max or min
arr with size n</> and current index start?Solution
Step 1: Check parameter order and types
The function needs the array, current index (start), and total size (n) to generate permutations recursively.Step 2: Validate return type and parameters
It should return void (no value) and have parameters (int arr[], int start, int n) in that order.Final Answer:
void permute(int arr[], int start, int n) -> Option AQuick Check:
Correct signature = void permute(arr, start, n) [OK]
- Wrong parameter order
- Incorrect return type
- Missing current index parameter
void permute(int arr[], int start, int n) {
if (start == n) {
for (int i = 0; i < n; i++) std::cout << arr[i] << ' ';
std::cout << '\n';
return;
}
for (int i = start; i < n; i++) {
std::swap(arr[start], arr[i]);
permute(arr, start + 1, n);
std::swap(arr[start], arr[i]);
}
}
int main() {
int arr[] = {1, 2};
permute(arr, 0, 2);
return 0;
}Solution
Step 1: Trace first call with arr = {1, 2}
Start = 0, n = 2. Swap arr[0] with arr[0] (no change), call permute with start=1.Step 2: Trace second call with start=1
Swap arr[1] with arr[1] (no change), call permute with start=2 which prints "1 2".Step 3: Backtrack and swap arr[0] with arr[1]
Array becomes {2, 1}, call permute with start=1 again.Step 4: At start=1 again, swap arr[1] with arr[1], call permute with start=2 prints "2 1".
Final Answer:
1 2 \n 2 1 \n -> Option BQuick Check:
All permutations of {1,2} printed [OK]
- Not swapping back after recursion
- Printing before base case
- Incorrect loop range
arr of size n:void permute(int arr[], int start, int n) {
if (start == n) {
for (int i = 0; i < n; i++) std::cout << arr[i] << ' ';
std::cout << '\n';
return;
}
for (int i = 0; i < n; i++) {
std::swap(arr[start], arr[i]);
permute(arr, start + 1, n);
std::swap(arr[start], arr[i]);
}
}Solution
Step 1: Analyze the for loop range
The loop swaps arr[start] with arr[i]. If i starts at 0 always, it swaps elements already fixed in previous recursion steps.Step 2: Correct loop start index
Loop should start from i = start to avoid repeating swaps and ensure correct permutations.Final Answer:
Loop should start from i = start, not 0 -> Option DQuick Check:
Loop from start to n fixes correct elements [OK]
- Starting loop from 0 causes repeated permutations
- Changing base case incorrectly
- Misplacing swap calls
arr = {1, 2, 2}, how many unique permutations will a correct C++ program generate if it avoids duplicates?Solution
Step 1: Calculate total permutations without duplicates
For 3 elements with two 2's, total permutations = 3! / 2! = 3.Step 2: List unique permutations
They are {1,2,2}, {2,1,2}, {2,2,1} -- total 3 unique permutations.Final Answer:
3 -> Option CQuick Check:
3! / 2! = 3 unique permutations [OK]
- Counting duplicates as unique permutations
- Using 3! = 6 without division
- Ignoring repeated elements
Ready to prove it?
Pass the test and this pattern moves unknown
