题目描述:给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
题目链接:LeetCode-47-全排列Ⅱ
解题思路:注意题目中给的是包含重复数字,所以需要去重操作;
- 这道题不需要 startIndex,因为每次都从下标 0开始,是排列问题;
- 终止条件是path.size()==nums.length,在每个叶子节点收获结果;
- 最重要的是去重操作,到底是树枝去重还是树层 去重?应该是都可以的,只是效率上来说树层去重更快一些,所谓的树层去重,就是 nums[i]==nums[i-1],以及前一个元素没有被使用过 used[i-1]==false。
代码实现:
java
class Solution {
// 和 46 全排列相比,多了2步去重的操作,树层去重
public List<List<Integer>> permuteUnique(int[] nums) {
Arrays.sort(nums);// 要先排序,方便处理相同的元素
backTracking(nums, new boolean[nums.length]);
return res;
}
List<List<Integer>> res = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public void backTracking(int[] nums, boolean[] used){
if (path.size()== nums.length){
res.add(new ArrayList<>(path));
return;
}
for (int i = 0; i < nums.length; i++) {
// used[i-1]=true : 说明树枝前一个元素已经取过
// used[i-1]=false : 说明树层前一个元素没有取过
// 如果同一个树层的元素使用过,则continue
if (i>0 && nums[i]==nums[i-1] && used[i-1]==false){// 树层去重,当前没有使用,并且和前一个数不相等
continue;
}
if (used[i]){// 当前的位置还没有使用过,必须加上这个判断,不然会有很多重复的组合
continue;
}
path.add(nums[i]);
used[i]=true;
backTracking(nums, used);
used[i]=false;
path.remove(path.size()-1);
}
}
}