题目
给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
示例 1:
输入:nums = [1,1,2] 输出: [[1,1,2], [1,2,1], [2,1,1]] 示例 2:
输入:nums = [1,2,3] 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
提示:1 <= nums.length <= 8
-10 <= nums[i] <= 10
思路
这题和全排列的区别在于,本题给定的是一个可以包含重复数字的序列,要返回所有不重复的全排列
注意:因为有相同元素的存在,所以去重操作会比正常去重多一个步骤——排序,这样才方便通过相邻节点去判断是否重复使用了
即一旦包含重复数字的去重,一定要先排序,然后判断相邻节点:
nums[i] == nums[i-1]
同时还需要一个used
数组,来标记是否在同一个排列中使用过
java代码如下:
//这里去重用到了uesd数组
class Solution {
List<List<Integer>> res =new ArrayList<>();
List<Integer> path =new ArrayList<>();
public List<List<Integer>> permuteUnique(int[] nums){
boolean[] used = new boolean[nums.length];
Arrays.fill(used,false);
Arrays.sort(nums);//先进行排序
backTracking(nums,used);
return res;
}
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,表示同一树枝nums[i-1]使用过,比如[1,1,0],前一个刚使用过
//used[i-1] == false,表示同一树层nums[i-1]使用过,比如[0,1,0],表示第一个元素在最开始就是使用过了
//如果同一树层nums[i-1]使用过则直接跳过
if(i > 0 && nums[i] == nums[i-1] && used[i-1] == false){
continue;
}
if(used[i] == false){
used[i] = true;
path.add(nums[i]);
backTracking(nums,used);
path.remove(path.size()-1);
used[i] = false;
}
}
}
}
注意:使用set去重的效率不如used数组去重