题目:https://leetcode-cn.com/problems/permutations-ii/
给定一个可包含重复数字的序列,返回所有不重复的全排列。
示例:
输入: [1,1,2]
输出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
参考:https://leetcode-cn.com/problems/permutations-ii/solution/quan-pai-lie-ii-by-leetcode-solution/
代码
class Solution {
boolean[] vis;
public List<List<Integer>> permuteUnique(int[] nums) {
// ans 为最终结果
List<List<Integer>> ans = new ArrayList<>();
// perm 是临时数组,用于存放可能的排列组合
List<Integer> perm = new ArrayList<>();
//通过vis来判断nums的值是否被使用过
vis = new boolean[nums.length];
//给数组排序,为去重准备
Arrays.sort(nums);
//递归回溯
backtrack(nums,ans,0,perm);
return ans;
}
/**
* 进入递归的第一步,先判断当前的idx是否等于数组的长度,若等于,则把perm添加进ans中,然后退出递归函数,返回递归的上一步
* 第二步:for循环数组其他每个剩余的值,若(i已经被访问)或者(i与i-1相等,且i-1没被访问过) 那么跳过当前循环。(解决重复问题)
*/
public void backtrack(int[] nums,List<List<Integer>> ans,int idx,List<Integer> perm){
// idx等于nums的长度时,把perm添加进ans中
if(idx == nums.length){
ans.add(new ArrayList<Integer>(perm));
return ;
}
// 循环 遍历每个数
for(int i=0;i<nums.length;i++){
//如果 i已被访问 或者 i>0 且 nums[i]等于nums[i-1] 且 [i-1]未被访问 则跳过本次循环
// 保证在填第 idx 个数的时候重复数字只会被填入一次
if(vis[i] || (i>0 && nums[i]==nums[i-1] && !vis[i-1])){
continue;
}
perm.add(nums[i]);
vis[i]=true;
backtrack(nums,ans,idx+1,perm);
vis[i]=false;
perm.remove(idx);
}
}
}