Generate All Permutations of Array in DSA C# - Time & Space Complexity
We want to understand how the time needed to generate all permutations grows as the array size increases.
How does the number of steps change when the array gets bigger?
Analyze the time complexity of the following code snippet.
void Permute(int[] arr, int start, List<List<int>> result) {
if (start == arr.Length) {
result.Add(new List<int>(arr));
return;
}
for (int i = start; i < arr.Length; i++) {
Swap(arr, start, i);
Permute(arr, start + 1, result);
Swap(arr, start, i);
}
}
void Swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
This code generates all possible orderings (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 recursion explores every possible ordering, which is factorial in the size of the array (n!).
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 | 5,040 (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 the input size increases by one.
Time Complexity: O(n!)
This means the time needed grows very fast as the array gets bigger, because we must explore every possible order.
[X] Wrong: "The time grows like n squared because of the nested loops."
[OK] Correct: The loops are inside recursive calls that multiply the work factorially, not just squared. So the growth is much faster than n squared.
Understanding this factorial growth helps you explain why generating all permutations is expensive and when it is practical to use in real problems.
"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
- Assuming permutations find max/min
Solution
Step 1: Identify input and output types
The input is an integer array, so parameter type is int[]. The output is all permutations, so a list of int arrays is suitable.Step 2: Match method signature
List GeneratePermutations(int[] nums) returns List and takes int[] as input, matching the requirement.Final Answer:
List GeneratePermutations(int[] nums) -> Option DQuick Check:
Input int[], output List of int[] [OK]
- Using void return type when output is needed
- Wrong parameter types like List<int> instead of int[]
- Returning int instead of list of arrays
var result = GeneratePermutations(new int[] {1, 2});
foreach(var perm in result) {
Console.WriteLine(string.Join(",", perm));
}
List GeneratePermutations(int[] nums) {
var list = new List();
void Backtrack(int start) {
if (start == nums.Length) {
list.Add((int[])nums.Clone());
return;
}
for (int i = start; i < nums.Length; i++) {
int temp = nums[start];
nums[start] = nums[i];
nums[i] = temp;
Backtrack(start + 1);
temp = nums[start];
nums[start] = nums[i];
nums[i] = temp;
}
}
Backtrack(0);
return list;
}Solution
Step 1: Understand the backtracking process
The code swaps elements starting from index 0 and generates permutations by recursive calls.Step 2: Trace permutations generated
For input [1,2], permutations are [1,2] and [2,1]. The code prints these in order.Final Answer:
1,2 2,1 -> Option AQuick Check:
Permutations of [1,2] = 1,2 and 2,1 [OK]
- Ignoring swap back to original after recursion
- Printing duplicates due to missing cloning
- Confusing order of permutations
void GeneratePermutations(int[] nums, int start, List result) {
if (start == nums.Length) {
result.Add(nums);
return;
}
for (int i = start; i < nums.Length; i++) {
int temp = nums[start];
nums[start] = nums[i];
nums[i] = temp;
GeneratePermutations(nums, start + 1, result);
temp = nums[start];
nums[start] = nums[i];
nums[i] = temp;
}
}Solution
Step 1: Analyze how results are stored
The code adds the original array reference to the result list without cloning.Step 2: Understand effect of adding reference
Since the array is modified later, all entries in result point to the same array, causing incorrect results.Final Answer:
The array is added directly without cloning, causing all entries to be the same -> Option AQuick Check:
Must clone array before adding to result [OK]
- Forgetting to clone array before adding
- Missing swap back causing wrong permutations
- Incorrect base case stopping too early
[1, 1, 2]. Which approach correctly handles duplicates to avoid repeated permutations?Solution
Step 1: Sort the array to group duplicates
Sorting helps detect duplicates easily during recursion.Step 2: Skip swapping duplicate elements
During recursion, skip swapping if the element is the same as a previously swapped one at the same recursion level to avoid repeated permutations.Final Answer:
Sort the array first, then skip swapping duplicate elements during recursion -> Option BQuick Check:
Sort + skip duplicates during recursion = unique permutations [OK]
- Generating all then removing duplicates (inefficient)
- Not sorting array before recursion
- Only swapping if values differ ignores position importance
Ready to prove it?
Pass the test and this pattern moves unknown
