题目:
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/2f3c42d01a2a4c9f89feda5bf52150fc.png)
思路:回溯
- 怎么确保回溯不重复?定义一个全局used数组。从而确定数字是否被使用
- 怎么避免重复排列生成?思路参照T40-组合Ⅱ,T90-子集Ⅱ,通过i>0 && nums[i]==nums[i-1] && !used[i-1]判断
代码:
class Solution {
List<List<Integer>> ans = new ArrayList<>();
List<Integer> path=new ArrayList<>();
boolean[] used;
public List<List<Integer>> permuteUnique(int[] nums) {
used = new boolean[nums.length];
Arrays.fill(used, false);
Arrays.sort(nums);
dfs(nums);
return ans;
}
public void dfs(int[] nums) {
if(path.size()==nums.length){
ans.add(new ArrayList<>(path));
}
for (int i = 0; i < nums.length; i++) {
if (i>0 && nums[i]==nums[i-1] && !used[i-1]){
continue;
} else if (used[i]==false) {
path.add(nums[i]);
used[i] = true;
dfs(nums);
used[i]=false;
path.removeLast();
}else{
continue;
}
}
}
}
注意点🔣:
- 要用逻辑&&而不是短路&,否则循环都启动不了(nums[0]==nums[-1]的逻辑判断会出现OutOfIndex异常)
- used[i- 1] == true或者false都行,但false的效率高点,因为第一层的回溯就能跳出相当大的部分了。 for循环是从左到右遍历(也就是比较当前节点与前一节点,默认情况又都是false),因此当前后节点值相同时,前一节点为false时即能跳出当前层的回溯,而true则不能(直到遍历到最后一个相等元素)。。。。我也不知道在说什么了,只可意会不可言传。。