发布于 

全排列 II

全排列 II(Permutations II) ⭐️⭐️⭐️

LeetCode每日一题 2020.09.18

给定一个可包含重复数字的序列,返回所有不重复的全排列。

Example:

1
2
3
4
5
6
7
输入: [1,1,2]
输出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]

解题思路

这道题目与 46.全排列的区别在与给定一个可包含重复数字的序列,要返回所有不重复的全排列。所以这里就涉及到去重了。所谓去重,其实就是使用过的元素不能重复选取。

全排列问题可以将结果看成一组数字的序列,我们需要从左往右依次填入题目给定的 n 个数,每个数只能使用一次(相同数字不同位置不冲突)。那么可以很直接的穷举出所有的可能性,即从左往右每一个位置都依此尝试填入一个数,此题用「回溯+剪枝法」来解决。

代码

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
func permuteUnique(nums []int) (res [][]int) {
vis := make([]bool, len(nums))
n := len(nums)
sort.Ints(nums)
var dfs func(nums, path []int, vis []bool)
dfs = func(nums, path []int, vis []bool) {
if n == len(path) {
res = append(res, append([]int(nil), path...))
return
}

for i := 0; i < len(nums); i++ {
if vis[i] { //该数已经被使用
continue
}
if i > 0 && nums[i] == nums[i-1] && vis[i-1] == false {
continue
}
vis[i] = true
dfs(nums, append(path, nums[i]), vis)
vis[i] = false
}
}

dfs(nums, nil, vis)
return
}

复杂度分析

  • 时间复杂度: O(N×N!)O(N\times N!),其中 N 为数组的长度。
  • 空间复杂度: O(N)O(N)