全排列1
本题:全排列2(要求去重)
我们选择对原数组排序,保证相同的数字都相邻,然后每次填入的数一定是这个数所在重复数集合中「从左往右第一个未被填过的数字」。
为什么“i>0&&!visited[i-1]&&nums[i-1]==nums[i]”中是“!visited[i-1]”?因为对于同一层而言,我们只选择相同数字的最左边一个未被填过的数字。如果visited[i-1]说明左边的数是上一层用过的,本层还可以用同样的数。如果!visited[i-1]说明本层可选左边的数,for循环的上一次已经用过,只是因为回溯时恢复了visited状态。
class Solution {
ArrayList<List<Integer>> res=new ArrayList<>();
int[] nums;
boolean[] visited;
public List<List<Integer>> permuteUnique(int[] nums) {
this.nums=nums;
Arrays.sort(this.nums);//排序,保证相同数字相连
this.visited=new boolean[nums.length];
dfs(new ArrayList<Integer>(0),0);
return res;
}
public void dfs(ArrayList<Integer> tmp,int index){
if(index==nums.length){//出现了一种排列
res.add(new ArrayList<>(tmp));//复制tmp到结果集
return;
}
for(int i=0;i<nums.length;i++){
if(visited[i]||(i>0&&!visited[i-1]&&nums[i-1]==nums[i])){
continue;
}
visited[i]=true;
tmp.add(nums[i]);
dfs(tmp,index+1);
tmp.remove(tmp.size()-1);
visited[i]=false;
}
}
}