给定一个 没有重复 数字的序列,返回其所有可能的全排列。
示例:
输入: [1, 2, 3]
输出:
[
[1, 2, 3],
[1, 3, 2],
[2, 1, 3],
[2, 3, 1],
[3, 1, 2],
[3, 2, 1]
]
题解
使用 visited
数组标记已访问过的元素。
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import java.util.*;
class Solution { public List<List<Integer>> permute(int[] nums) { List<List<Integer>> results = new ArrayList<>(); dfs(results, nums, new ArrayList<>(), new int[nums.length]);
return results; }
public void dfs(List<List<Integer>> results, int[] nums, ArrayList<Integer> tmp, int[] visited) { if (tmp.size() == nums.length) { results.add(new ArrayList<>(tmp)); return; }
for (int i = 0; i < nums.length; i++) { if (visited[i] == 1) continue; tmp.add(nums[i]); visited[i] = 1; dfs(results, nums, tmp, visited); visited[i] = 0; tmp.remove(tmp.size() - 1); } } }
|
Python
使用切片和 list
的加法,在向下递归时略过当前元素即实现了对访问过元素的标记。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Solution: def permute(self, nums: list) -> list: results = [] def dfs(nums, tmp): if not nums: results.append(tmp) return for i in range(len(nums)): dfs(nums[:i] + nums[i + 1:], tmp + [nums[i]]) dfs(nums, []) return results
def permute1(self, nums: list) -> list: return list(itertools.permutations(nums))
|
调用 Python
的内置函数实现如下
1 2 3 4 5
| import itertools
class Solution: def permute(self, nums: list) -> list: return list(itertools.permutations(nums))
|
Go
Go
在实现时需注意 append(nums, 2)
不会修改 nums
数组存储的内容,但 append(nums[:i], 2)
会使 nums
数组发生改变。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| package main
import "fmt"
func permute(nums []int) [][]int { var results [][]int dfs(&results, nums, []int{})
return results }
func dfs(results *[][]int, nums, tmp []int) { if len(nums) == 0 { *results = append(*results, append([]int{}, tmp...)) return }
for i := 0; i < len(nums); i++ { dfs(results, combinedArr(nums[:i], nums[i+1:]), combinedArr(tmp, []int{nums[i]})) } }
func combinedArr(arr1, arr2 []int) []int { var result []int result = append(result, arr1...) result = append(result, arr2...)
return result }
|
给定一个可包含重复数字的序列,返回所有不重复的全排列。
示例:
输入: [1, 1, 2]
输出:
[
[1, 1, 2],
[1, 2, 1],
[2, 1, 1]
]
题解
参考题解
#46 中的算法流程如下,因 #47 包含重复元素,需对递归树进行剪枝:
观察可知,若两个分支的前几位排列相同,则这两个分支上的递归子树也相等,如 [1]
与 [1']
、[2, 1]
与 [2, 1']
(即图上红框中内容)重复,可进行剪枝,在同一层判断 nums[i] == nums[i - 1]
是否成立即可。若只设定这一个剪枝条件,将使以下蓝框中的分支被误剪,导致返回空的解集:
为避免这种现象的产生,可借助 visited
数组对是否遍历过某分支进行标记,仅在前一个分支遍历完成(即 visited[i - 1] == 0
成立时)进行剪枝。故剪枝的判断条件为 i > 0 && nums[i] == nums[i - 1] && visited[i - 1] == 0
。
下图为递归时递归栈的调用顺序:
注: 实际上 visited[i - 1]
等于 0、不等于 0、等于 1、不等于 1 四种情况下产生的结果相同,但若直接去掉则将返回空的解集🙃。visited[i - 1]
起到的是标记的作用,即只选择 visited[i - 1]
等于 0 或只选择等于 1 的分支,区别仅在于最终结果集中元素的顺序不同,详见 这篇题解 的补充说明部分。
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| class Solution { public List<List<Integer>> permuteUnique(int[] nums) { List<List<Integer>> res = new ArrayList<>(); Arrays.sort(nums); dfs(res, nums, new ArrayList<>(), new int[nums.length]); return res; }
public void dfs(List<List<Integer>> res, int[] nums, List<Integer> tmp, int[] visited) { if (tmp.size() == nums.length) { res.add(new ArrayList<>(tmp)); return; }
for (int i = 0; i < nums.length; i++) { if (visited[i] == 1) continue;
if (i > 0 && nums[i] == nums[i - 1] && visited[i - 1] == 0) continue;
tmp.add(nums[i]); visited[i] = 1; dfs(res, nums, tmp, visited); visited[i] = 0; tmp.remove(tmp.size() - 1); } } }
|
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class Solution: def permuteUnique(self, nums: list) -> list: results = [] arr_len = len(nums) def dfs(tmp: list, visited: list): if len(tmp) == arr_len: results.append(tmp[:]) return
for i in range(arr_len): if visited[i] or (i > 0 and nums[i] == nums[i - 1] and not visited[i - 1]): continue tmp.append(nums[i]) visited[i] = 1 dfs(tmp, visited) visited[i] = 0 tmp.pop()
nums.sort() dfs([], [0] * len(nums)) return results
|
Go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| import "sort"
func permuteUnique(nums []int) [][]int { var results [][]int sort.Ints(nums) arrLen := len(nums) dfs(&results, nums, []int{}, make([]int, arrLen), arrLen)
return results }
func dfs(results *[][]int, nums, tmp, visited []int, arrLen int) { if len(tmp) == arrLen { *results = append(*results, append([]int{}, tmp...)) // 注意深拷贝 return }
for i := 0; i < arrLen; i++ { if visited[i] == 1 || (i > 0 && nums[i] == nums[i - 1] && visited[i - 1] == 0) { continue } tmp = append(tmp, nums[i]) visited[i] = 1 dfs(results, nums, tmp, visited, arrLen) tmp = tmp[:len(tmp) - 1] visited[i] = 0 } }
|
其它解法
仿写 C++ 中的 nextPermutation
函数,该解法 #46、#47 均可 AC。
详见 下一个排列
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| import java.util.*;
class Solution { public List<List<Integer>> permuteUnique(int[] nums) { List<List<Integer>> results = new ArrayList<>(); Arrays.sort(nums); results.add(arrToList(nums)); while (nextPermutation(nums)) { results.add(arrToList(nums)); }
return results; }
public List<Integer> arrToList(int[] nums) { List<Integer> result = new ArrayList<>(); for (int num : nums) result.add(num); return result; }
public boolean nextPermutation(int[] nums) { int arrLen = nums.length; int i = arrLen - 2, j = arrLen - 1, k = arrLen - 1;
while (i >= 0 && nums[i] >= nums[j]) { i--; j--; }
if (i == -1) return false;
while (nums[i] >= nums[k]) k--; swap(nums, i, k);
for (i = j, j = arrLen - 1; i < j; i++, j--) { swap(nums, i, j); }
return true; }
public void swap(int[] nums, int i, int j) { int tmp = nums[i]; nums[i] = nums[j]; nums[j] = tmp; } }
|
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| class Solution: def permuteUnique(self, nums: list) -> list: results = [] arr_len = len(nums)
def next_permutation() -> bool: i, j, k = arr_len - 2, arr_len - 1, arr_len - 1
while i >= 0 and nums[i] >= nums[j]: i -= 1 j -= 1
if i == -1: return False
while nums[i] >= nums[k]: k -= 1 nums[i], nums[k] = nums[k], nums[i]
i, j = j, arr_len - 1 while i < j: nums[i], nums[j] = nums[j], nums[i] i += 1 j -= 1
return True
nums.sort() results.append(nums[:]) while next_permutation(): results.append(nums[:])
return results
|
Go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| import "sort"
func permuteUnique(nums []int) [][]int { var results [][]int arrLen := len(nums) sort.Ints(nums) results = append(results, append([]int{}, nums...))
for nextPermutation(nums, arrLen) { results = append(results, append([]int{}, nums...)) }
return results }
func nextPermutation(nums []int, arrLen int) bool { i, j, k := arrLen - 2, arrLen - 1, arrLen - 1
for i >= 0 && nums[i] >= nums[j] { i-- j-- }
if i == -1 { return false }
for nums[i] >= nums[k] { k-- } nums[i], nums[k] = nums[k], nums[i]
for i, j = j, arrLen - 1; i < j; i, j = i + 1, j - 1 { nums[i], nums[j] = nums[j], nums[i] }
return true }
|