给定一个可包含重复数字的序列 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
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/permutations-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
int len= nums.length;
List<List<Integer>> res=new ArrayList<>();
if (len==0){
return res;
}
Arrays.sort(nums);
boolean[] used=new boolean[len];
Deque<Integer> path=new ArrayDeque<>(len);
dfs(nums,len,0,used,path,res);
return res;
}
private void dfs(int[] nums, int len, int depth, boolean[] used, Deque<Integer> path, List<List<Integer>> res) {
if (depth==len){
res.add(new ArrayList<>(path));
return;
}
for (int i = 0; i < len; i++) {
if (used[i]){
continue;
}
if (i>0&&nums[i]==nums[i-1]&&!used[i-1]){
continue;
}
path.addLast(nums[i]);
used[i]=true;
dfs(nums,len,depth+1,used,path,res);
used[i]=false;
path.removeLast();
}
}
}
为什么要先排序 因为结果是要去重的,而结果都是列表形式的,那列表怎么判重呢?就是排序之后一个一个的比较,所以那还不如先排序之后再计算,再计算的过程中判断是否有重复,免得对每个结果再做一次排序去重操作。
怎么判断当前分支是否是重复的分支。 因为之前已经拍好序了,所以当前元素nums[i] 如果和前一个元素相同 ,即nums[i] == nums[i-1]就说明该分支 有可能 是重复的。 但是这个相等条件有两种可能 一种是,1 1‘ 2,也就是选择完1之后再选择第二个1,两个元素虽然重复,但是第二个元素是前一个元素的下一层,这时是没有问题的。 另一种是之前的 同层 分支已经有 1 1‘ 2了,这次的选择是 1‘ 1 2 。两个元素重复,且重的是同层路径。那就说明是重复分支。
具体区分的办法是 nums[i-1] 的used状态是被选择的,那么说明当前的nums[i] 是 nums[i-1]的下一层路径。 否则如果 nums[i-1] 的状态是没被选择的,那么说明当前 的nums[i] 是nums[i-1] 同层路径。