这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战
前言
关于 LeetCode 数组类型题目的相关解法,可见LeetCode 数组类型题目做前必看,分类别解法总结了题目,可以用来单项提高。觉得有帮助的话,记得多多点赞关注哦,感谢!
题目描述
给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。
示例 1:
输入:nums = [1,2,2]
输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]
示例 2:
输入:nums = [0]
输出:[[],[0]]
链接:leetcode-cn.com/problems/su…
题解
这道题和 leetcode 78 基本一样,唯一的差别是这道题目存在重复元素,如果还按照原来的方法,最后的结果中会包含重复的子集。我们需要找方法排除重复的子集。
一个简单的办法是我们利用 Set 来排除重复子集,但是 JS 中我们需要先将数组转换为字符串,否则 Set 将无法去重,它认为 [1, 2] 和 [1, 2] 是两个不同的数组。
一个更好的方法是我们自己来去重。分为两步,第一步是排序,让相同的元素相邻,这样在递归的时候我们就能判断是否重复。第二步是在递归的时候,我们需要判断当前下标 i 是否已经出现过了。如果已经出现过了,就跳过 i ,进行下一个数字的递归。
具体代码如下:
/**
* @param {number[]} nums
* @return {number[][]}
*/
var subsetsWithDup = function(nums) {
let ans = [[]]
let curr = []
nums.sort((a, b) => a-b)
for (let i = 1; i <= nums.length; i++)
dfs(curr, nums, 0, i, 0, ans)
return ans
};
var dfs = (curr, nums, d, n, s, ans) => {
if (d === n) {
ans.push([...curr])
return
}
for (let i=s; i < nums.length; i++) {
// 是否已经出现过
if (i > s && nums[i-1] === nums[i]) continue
curr.push(nums[i])
dfs(curr, nums, d+1, n, i+1, ans)
curr.pop()
}
}