题目描述
给定一个可包含重复数字的序列 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.com/problems/permutations-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
与【LeetCode】第46题——全排列(难度:中等)相比,本题的难点在于重复结果的降重,具体来说就对于答案[2,1,1](第一个1的下标为0,第二个1的下标为1)和[2,1,1](第一个1的下标为一,第二个1的下标为0)的降重。
其实也就是再加一个set的问题,在循环体中加入set(注意是循环而非递归)
代码详解
class Solution {
List<List<Integer>> ans = new ArrayList<>();
public List<List<Integer>> permuteUnique(int[] nums) {
Set<Integer> hs = new HashSet<>(); // hs这个set就是用于结果降重的,在for循环体中只对同一个值的元素遍历一次
for(int i = 0; i < nums.length; ++i) {
if(!hs.add(nums[i])) {
continue;
}
HashSet<Integer> tempSet = new HashSet<>(); // tempSet是用于传递的set,用于防止被使用过的元素被重复使用
tempSet.add(i);
func(i, nums, new ArrayList<>(), tempSet);
}
return ans;
}
public void func(int index, int[] nums, ArrayList<Integer> list, HashSet<Integer> set) {
// 对于list和set这两个参数都是先用浅复制,然后再进行处理
ArrayList<Integer> tempList = new ArrayList<>(list); // tempList用于保存经过的节点
tempList.add(nums[index]);
if(tempList.size() == nums.length) {
ans.add(tempList);
} else {
Set<Integer> hs = new HashSet<>(); // hs作用同上
for(int i = 0; i < nums.length; ++i) {
HashSet<Integer> tempSet = new HashSet<>(set); // tempSet的作用同上
if(!tempSet.add(i)) {
continue;
}
if(!hs.add(nums[i])) {
continue;
}
func(i, nums, tempList, tempSet);
}
}
}
}
注意点
- 注意答案[2,1,1](第一个1的下标为0,第二个1的下标为1)和[2,1,1](第一个1的下标为一,第二个1的下标为0)的降重
- 友情链接:【LeetCode】第46题——全排列(难度:中等)