Permutation
Question
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]]
Solution
Permutation is similar to Subset however we only get the final result
Time Complexity: $O(n!)$
Example: https://leetcode.com/problems/permutations/
Input: nums = [1,2,3]
Output: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
class App:
result: List[int]
frequency: Dict[int, int]
def permute(self, nums: List[int]) -> List[List[int]]:
self.result = []
self._permute(nums)
return self.result
def _permute(self, nums: List[int], basket: List[int] = []):
if (len(basket) == len(nums)):
self.result.append(basket.copy())
return
for num in nums:
if num in basket: continue
basket.append(num)
self._permute(nums, basket)
basket.pop()
In contrast to the Subset > ^473ad2 we're not using for i
loop. The reason is we want to pick all the possible numbers in nums without skipping any number. In here we want to choose if num not in basket
because we masively add it in.
Permutation duplication
https://leetcode.com/problems/permutations-ii/
In this question, the number could appear multiple time, for example in here number 1
appears twice in nums
Input: nums = [1,1,2]
Output:
[[1,1,2],
[1,2,1],
[2,1,1]]
Using like the previous method wouldn't work because now we are having duplication in nums
we can't simply check if num not in tmp
anymore - since it could refer to another number (not the same)
Intuition:
The idea is we need keep track of how many numbers we allowed to used. In the example above, we have 2 1
's and 1 2
's
Next, we need to loop using the frequency
this is because now we want to work with the dictionary to group these numbers together. We go through each of the number in the dictionary itself and check if we can use it.
class App:
result: List[int]
frequency: Dict[int, int]
def permute(self, nums: List[int]) -> List[List[int]]:
self.frequency = Counter(nums)
self.result = []
self._permute(nums)
return self.result
def _permute(self, nums: List[int], basket: List[int] = []):
if (len(basket) == len(nums)):
self.result.append(basket.copy())
return
for num in nums:
if self.frequency[num] <= 0: continue
basket.append(num)
self.frequency[num] -= 1
self._permute(nums, basket)
self.frequency[basket.pop()] += 1
If we loop using the nums
itself, it will create duplicated result. For example:
- If we loop through
[1,1,2]
- After the end of
2
, we have{1: 0, 2: 1}
in the counter and ourtmp = [1,1,2]
, now we're backtracking back - We pop
2
out, we have{1: 0, 2: 0}
,tmp = [1,1]
- We pop
1
out, we have{1: 1, 2: 1}
,tmp = [1]
- Now we're at the inital
1
, What happens now?- Since we have
{1: 1, 2: 1}
again, it will make[1,1,2]
again and put it in the result
- Since we have
- After the end of
Note: difference between this method (using Counter
and Subset > Subset duplication) is using counter allows the same element to have different position:
For example, you can have both [2,2,1]
and [1,2,2]
in the result. Subset > Subset duplication does not allow that