Permutations
LeetCode 46 | Difficulty: Mediumβ
Problem Descriptionβ
Given an array nums of distinct integers, return all the possible permutations. You can return the answer in any order.
Constraintsβ
1 <= nums.length <= 6-10 <= nums[i] <= 10- All the integers of
numsare unique
Examplesβ
Example 1:
Input: nums = [1,2,3]
Output: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
Example 2:
Input: nums = [0,1]
Output: [[0,1],[1,0]]
Example 3:
Input: nums = [1]
Output: [[1]]
Approachβ
This is a classic backtracking problem. The key idea is to build permutations incrementally:
- Choose: Pick an unvisited element to add to the current permutation
- Explore: Recursively build the rest of the permutation
- Unchoose: Remove the element and mark it as unvisited (backtrack)
The Backtracking Template:
void backtrack(state, choices):
if state is complete:
add state to results
return
for each choice in choices:
if choice is valid:
make choice
backtrack(new_state, remaining_choices)
undo choice // backtrack
Complexity Analysisβ
- Time Complexity: $O(N \times N!)$ β There are $N!$ permutations, and copying each takes $O(N)$
- Space Complexity: $O(N)$ β Recursion stack depth and the
visitedarray (excluding output)
Solutionβ
public IList<IList<int>> Permutation(int[] nums)
{
IList<IList<int>> result = new List<IList<int>>();
bool[] visited = new bool[nums.Length];
Backtrack(nums, visited, new List<int>(), result);
return result;
}
void Backtrack(int[] nums, bool[] visited, List<int> current, IList<IList<int>> result)
{
// Base case: permutation is complete
if (current.Count == nums.Length)
{
result.Add(current.ToList()); // Add a copy
return;
}
// Try each unvisited element
for (int i = 0; i < nums.Length; i++)
{
if (visited[i]) continue; // Skip if already used
// Choose
visited[i] = true;
current.Add(nums[i]);
// Explore
Backtrack(nums, visited, current, result);
// Unchoose (backtrack)
visited[i] = false;
current.RemoveAt(current.Count - 1);
}
}
Interview Tipsβ
- Why use
ToList()? β Lists are passed by reference; without copying, all results would point to the same (empty) list - Alternative: Swap-based approach β Instead of visited array, swap elements in place:
void Backtrack(int[] nums, int start, IList<IList<int>> result) {
if (start == nums.Length) { result.Add(nums.ToList()); return; }
for (int i = start; i < nums.Length; i++) {
Swap(nums, start, i);
Backtrack(nums, start + 1, result);
Swap(nums, start, i); // backtrack
}
} - Common Follow-ups:
- What if duplicates exist? β See Permutations II
- Return the k-th permutation? β See Permutation Sequence
Related Problemsβ
- 47. Permutations II β Handle duplicate elements by sorting and skipping
- 31. Next Permutation β Find next lexicographic permutation in-place
- 60. Permutation Sequence β Return the k-th permutation directly
- 78. Subsets β Similar backtracking pattern for power set