题目
给定一个可包含重复数字的序列,返回所有不重复的全排列。
示例:
输入: [1,1,2]
输出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
方案:DFS+剪枝
- 思路大体都差不太多,我是参考官方的思路
- 先排序,那么大小相同的就会在一起,在这个数没访问过的前提下,我们只允许以下三种情况进入下一轮:
- 第一个(i==0)
- 与前一个相同但是前一个被访问过
- 与前一个不同
- 1、3两种比较好理解,2主要是为了强制相等的数的取法是按照顺序来的,这样就不会发生相等的数进行排列组合从而导致重复的情况发生
class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> res = new ArrayList<>( );
Arrays.sort(nums);
DFS(res, nums, new ArrayDeque<>( ), new boolean[nums.length]);
return res;
}
public void DFS(List<List<Integer>> res, int[] nums, Deque<Integer> arrange, boolean[] isVisited) {
if (nums.length == arrange.size( )) {
res.add(new ArrayList<>(arrange));
return;
}
for (int i = 0; i < nums.length; i++) {
if (!isVisited[i]) {
if (i == 0 || (nums[i]==nums[i-1]&&isVisited[i - 1])||nums[i]!=nums[i-1]) {
arrange.add(nums[i]);
isVisited[i] = true;
DFS(res, nums, arrange, isVisited);
arrange.removeLast( );
isVisited[i] = false;
}
}
}
}
}
复杂度计算
- 时间复杂度:O(n!)
- 空间复杂度:O(n!)
- 二者最差的情况都是(n*n!),也就是不剪枝那种