47. 全排列 II
题目描述
给定一个可包含重复数字的序列 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
题解
思路
- 对比全排列那道题目,这里需要处理重复的情况
- 所以需要每层定义一个used数组或者set集合,去处理
- 这里虽然改变原数组之后,不影响结果,但是依然不能够使用排序后去重的方式去做,因为这里的递归进入下一层后,选取的范围依然是nums数组的全部,而不是
[startIndex, end)
这个范围,i != 0 && nums[i] == nums[i - 1]
用这个方式去重,会导致,下一层元素也会因为和上层重复而去掉,而在排列中,我需要去掉的是上层同位置的元素,而不是值相等的元素
代码
class Solution {
List<List<Integer>> res;
List<Integer> path;
public List<List<Integer>> permuteUnique(int[] nums) {
res = new ArrayList<>();
path = new ArrayList<>();
backTracking(nums, new boolean[nums.length]);
return res;
}
public void backTracking(int[] nums, boolean[] used) {
if(nums.length == path.size()) {
res.add(new ArrayList<>(path));
return;
}
Set<Integer> set = new HashSet<>();
for(int i = 0; i < nums.length; i++) {
// set是去除同一层的重复元素
// 这里去除同一层重复元素不能用以前的方式 i != 0 && nums[i] == nums[i - 1]
// 因为这里是排列,每一层都是同样区间的nums数组,所以会导致下一层也会被去重(i != 0 和 i != startIndex)
// used是去除隔层的重复位置
if(set.contains(nums[i]) || used[i])
continue;
set.add(nums[i]);
used[i] = true;
path.add(nums[i]);
backTracking(nums, used);
path.remove(path.size() - 1);
used[i] = false;
}
}
}