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(int *arr, int start, int end) {
if (start == end) {
// print or store the permutation
return;
}
for (int i = start; i <= end; i++) {
swap(&arr[start], &arr[i]);
permute(arr, start + 1, end);
swap(&arr[start], &arr[i]);
}
}
This code generates all possible orders (permutations) of the array elements by swapping and recursively exploring each choice.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursive calls combined with a loop that swaps elements.
- How many times: The function calls itself for every possible arrangement, which grows very fast as the array size increases.
Each time we add one more element, the number of possible orders multiplies by that new number.
| 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 by multiplying all numbers from 1 up to n, which is very fast growth.
Time Complexity: O(n!)
This means the time needed grows very fast, multiplying by a bigger number each time we add an element.
[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 many times, so the growth is much faster than simple loops.
Understanding this growth helps you explain why generating all permutations is expensive and when it's practical to do so.
"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 CQuick Check:
Permutations = all orders [OK]
- Confusing permutations with sorting
- Thinking permutations remove duplicates
- Mixing permutations with finding max/min
arr of size n?Solution
Step 1: Understand recursion base case
The base case occurs when the start index reaches the array size, meaning a full permutation is formed.Step 2: Match base case condition
Conditionstart == nmeans all positions are fixed, so print the permutation and return.Final Answer:
if (start == n) { print(arr); return; } -> Option BQuick Check:
Base case when start equals array size [OK]
- Using start > n instead of start == n
- Printing when start == 0 (start of recursion)
- Missing base case leading to infinite recursion
void permute(int *arr, int start, int n) {
if (start == n) {
for (int i = 0; i < n; i++) printf("%d ", arr[i]);
printf("\n");
return;
}
for (int i = start; i < n; i++) {
int temp = arr[start];
arr[start] = arr[i];
arr[i] = temp;
permute(arr, start + 1, n);
temp = arr[start];
arr[start] = arr[i];
arr[i] = temp;
}
}
int main() {
int arr[] = {1, 2};
permute(arr, 0, 2);
return 0;
}Solution
Step 1: Trace first call permute(arr, 0, 2)
Start=0, loop i=0 to 1. Swap arr[0] with arr[0], call permute(arr,1,2).Step 2: Trace second call permute(arr, 1, 2)
Start=1, loop i=1 to 1. Swap arr[1] with arr[1], call permute(arr,2,2). Base case reached, print "1 2".Step 3: Backtrack and swap arr[0] with arr[1]
Now arr = {2,1}. Call permute(arr,1,2) again, print "2 1".Final Answer:
1 2 2 1 -> Option AQuick Check:
All permutations of [1,2] printed [OK]
- Not swapping back after recursive call
- Printing incomplete permutations
- Confusing loop indices
arr of size n:void permute(int *arr, int start, int n) {
if (start == n) {
for (int i = 0; i < n; i++) printf("%d ", arr[i]);
printf("\n");
return;
}
for (int i = start; i < n; i++) {
int temp = arr[start];
arr[start] = arr[i];
arr[i] = temp;
permute(arr, start + 1, n);
// Missing swap back here
}
}Solution
Step 1: Understand swap and backtrack
After swapping and recursive call, we must swap back to restore original array for next iteration.Step 2: Identify missing swap back
The comment shows swap back is missing, so array stays changed, causing wrong permutations.Final Answer:
Missing swap back after recursive call causes incorrect permutations -> Option AQuick Check:
Swap back needed to restore array [OK]
- Forgetting to swap back after recursion
- Changing loop range incorrectly
- Wrong base case condition
arr = {1, 2, 2}, how many unique permutations will a correct algorithm generate that 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
Unique permutations are: [1,2,2], [2,1,2], [2,2,1]. But careful with counting duplicates in generation.Step 3: Consider correct algorithm avoiding duplicates
Some algorithms generate 4 permutations including one duplicate if not careful, but correct unique count is 3.Final Answer:
3 -> Option DQuick Check:
Unique permutations = 3 [OK]
- Counting duplicates as unique permutations
- Ignoring duplicate elements in calculation
- Assuming all permutations are unique
Ready to prove it?
Pass the test and this pattern moves unknown
