题目描述
给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。
样例
示例1:
输入:nums = [1,2,2]
输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]
示例2:
输入:nums = [0]
输出:[[],[0]]
思路
简单的思路是 dfs,从前往后遍历每个元素,每个元素都可以加入或是不加入结果子集。
但是这样会有一个重复问题,碰到重复元素就可能会生成相同的子集。
因此,可以先对nums数组排序,在dfs的时候,如果当前元素与上一个元素值相同,并且进入该层dfs时没有选择上一个元素,那么本层dfs就可以跳过,不用再考虑选择本层元素的情况。
例如,[1,2,2]这个数组,对于前两个元素,我们可以生成[],[1],[2],[1,2]这4个子集。而当dfs到第二个2时,当之前dfs的子集为[1]时,如果我们再加入这个2,就又会生成[1,2],这就重复了。
表达的可能不是特别清楚,这里可以参考一下官方题解:
嘤嘤嘤我是传送门
代码
class Solution {
List<Integer> ls = new ArrayList<Integer>();
List<List<Integer>> result = new ArrayList<List<Integer>>();
public List<List<Integer>> subsetsWithDup(int[] nums) {
Arrays.parallelSort(nums);
dfs(false,0,nums);
return result;
}
public void dfs(boolean flag,int cur,int[] nums) {
if(cur == nums.length) {
result.add(new ArrayList<Integer>(ls));
return;
}
//没有选当前元素的分支
dfs(false,cur+1,nums);
//如果当前元素和前一个元素一样,并且前一个元素没选,则跳过生成当前子集。
if(flag == false && cur >= 1 && nums[cur] == nums[cur-1]) {
return;
}
//选了当前元素的分支
ls.add(nums[cur]);
dfs(true,cur+1,nums);
ls.remove(ls.size()-1);
}
}