46. Permutations Medium
Given an array nums of distinct integers, return all the possible permutations. You can return the answer in any order.
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
Input: An integer array nums without duplicate numbers.
Output: Return all possible permutation results.
This problem belongs to Permutation Backtracking problems.
- We need to choose a number at each position, ensuring every number appears exactly once.
- Use
pathto save the current permutation result. - Use a set
sto keep track of the remaining numbers available to pick. - When the length of
pathequals the length ofnums, it indicates the current sequence is a complete permutation, and we can save it to the answer. - After selecting a number, remove it from the available set
s, and then recurse into the next level. - When backtracking, we must undo the choice and remove the number from
path.
Three Questions of Backtracking
Current Operation?
- At the current position
i(how many numbers selected so far), try selecting an unselected numberxfrom setsto put into the current sequencepath. - Specifically, adding number
xtopath, representing "I chose this number".
- At the current position
Sub-problem?
- After choosing number
x, we need to recursively construct the rest of the permutation. - Namely, continuing to select the next number from
s - {x}.
- After choosing number
Next Sub-problem?
- The next recursive step is calling
dfs(i + 1, s - {x}), processing choices from the remaining candidates until the sequence length equalsn.
- The next recursive step is calling
Pruning Conditions
- A number
xcan only be selected if it still exists in the sets. - When the sequence length reaches
n, the current permutation is appended to the answer. - As the problem guarantees no duplicates in
nums, we don't need deduplication on the results.
Implementation
python
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
ans = [] # To store all permutations
path = [] # To store the current permutation path
n = len(nums) # Length of the array
def dfs(i, s):
"""
i: current recursion depth, representing how many numbers are selected
s: remaining numbers available to be selected (set)
"""
if i == n:
# When the permutation length reaches the array length, a valid permutation is formed
ans.append(path.copy())
return
for x in nums:
# We can only choose number x if it hasn't been chosen yet (exists in s)
if x in s:
path.append(x) # Choose number x
dfs(i + 1, s - {x}) # Recurse to the next level, removing x from set s
path.pop() # Backtrack, undo choice, and try another number
dfs(0, set(nums)) # Start from layer 0, initially all numbers can be selected
return ansjavascript
/**
* @param {number[]} nums
* @return {number[][]}
*/
var permute = function(nums) {
const ans = []; // Store all the permutations
const path = []; // Journey of current permutation
const unUsed = new Set(nums); // Track unchosen numbers (Using Set for quick lookup)
/**
* @param {number} i Current depth of recursion
* @param {Set} s Set of available choices remaining
*/
function dfs(i, s) {
// If we have selected nums.length digits, a permutation is found
if (i === nums.length) {
ans.push([...path]); // Store the deep-copy of current valid permutation
return;
}
// Enumerate over all elements to consider
for (let x of nums) {
if (s.has(x)) { // Number chosen must not have been previously visited
path.push(x); // Select current digit
s.delete(x); // Mark as "used"
dfs(i + 1, s); // Continue constructing next levels
// Backtrack: Undo choice
s.add(x); // Set back to "unused"
path.pop(); // Take out of subset representation
}
}
}
dfs(0, unUsed); // Start from layer 0, initially the available set is everything
return ans; // Return formed permutations
};Complexity Analysis
- Time Complexity:
O(n * n!) - Space Complexity:
O(n * n!)