题目:
Given a collection of integers that might contain duplicates, nums, return all possible subsets.
Note:
- Elements in a subset must be in non-descending order.
- The solution set must not contain duplicate subsets.
For example,
If nums = [1,2,2]
, a solution is:
[ [2], [1], [1,2,2], [2,2], [1,2], [] ]题意:
给定一个可能包含重复元素的数组,返回所有可能子集合。
note:
1、每个子集合中的元素都按照递增顺序;
2、返回set集合中不能包含重复的子集合;
思路:
如果存在重复元素,其中的一个重复元素按照之前的方法放置,再将重复元素作为一个整体放置到各个子集合中。
轮询;nums = [1,2,2]
生成所有子集合的过程如下所示:
1、初始化:[[]]
2、添加第一个元素之后所有的子元素集合为:[
[]
,
[1]
]
; (在前面一个集合中添1构成新子集);
3、添加第二个元素以及重复元素之后所有的子元素集合为:[ [],[1],[2],[2,2],[1,2],[1,2,2];(在前面两个自己中分别添2构成新子集);
黄色部分为添加第一个2,蓝色部分为添加第二个重复的2;代码:12ms
class Solution { public: vector<vector<int>> subsetsWithDup(vector<int>& nums) { vector<vector<int>> result(1, vector<int>()); sort(nums.begin(), nums.end()); //先对数组排序 for(int i=0; i<nums.size(); ){ //数组元素轮训 int count = 0; while(i+count < nums.size() && nums[count+i]==nums[i]){ count++; //重复元素计数,count==1正常,count>1有重复元素 } int preN = result.size(); //上一次循环后,result中存在的集合个数 for(int j=0; j<preN; j++){ //轮训上一次循环后所有的子集合 vector<int> cur = result[j]; //获取上一次循环后每一个子集合 for(int k=0; k<count; k++){ //针对于重复元素处理 cur.push_back(nums[i]); result.push_back(cur); } } i += count; //跳过重复元素 } return result; } };
思路二:
轮询;nums = [1,2,2]
生成所有子集合的过程如下所示:
1、初始化:[[]]
2、添加第一个元素之后所有的子元素集合为:[
[]
,
[1]
]
; (在前面一个集合中添1构成新子集);
黄色部分为添加第一个2,灰色部分为添加第二个重复的2;
代码:12ms
class Solution { public: vector<vector<int>> subsetsWithDup(vector<int>& nums) { vector<vector<int>> result(1, vector<int>()); sort(nums.begin(), nums.end()); //先对数组排序 int size = 0; int startIndex = 0; for(int i=0; i<nums.size(); i++){ //轮训所有数组元素 startIndex = (i>=1 && (nums[i]==nums[i-1])) ? size : 0; //如果没有重复元素startIndex=0,有重复元素,则startIndex=size(上一次所有子集合的数目) size = result.size(); for(int j=startIndex; j<size; j++){ //不是重复元素,就将所有子集合中添加一个。重复元素则只添加重复的部分 vector<int> tmp = result[j]; tmp.push_back(nums[i]); result.push_back(tmp); } } return result; } };思路三:
DFS,深搜。
代码:12ms
class Solution { public: vector<vector<int>> subsetsWithDup(vector<int>& nums) { sort(nums.begin(), nums.end()); //先对数组排序 vector<vector<int>> result; vector<int> pre; result.push_back(pre); dfs(result, pre, nums, 0); return result; } void dfs(vector<vector<int>> &res, vector<int>& pre, vector<int>&nums, int k){ if (k>=nums.size()) { return; } for (int i=k;i<nums.size();i++){ if (nums[i]!=nums[i-1] || i==k){ pre.push_back(nums[i]); res.push_back(pre); // for empty set; dfs(res,pre,nums,i+1); pre.pop_back(); } } } };代码:8ms 时间复杂度最低
class Solution { public: vector<vector<int>> subsetsWithDup(vector<int>& nums) { sort(nums.begin(),nums.end()); vector<int>temp; vector<vector<int>>result; f(nums,result,0,temp); return result; } void f(vector<int>& nums,vector<vector<int>>&result,int i,vector<int>&temp){ if(i==nums.size()){ result.push_back(temp); return; } temp.push_back(nums[i]); int j=i+1; f(nums,result,j,temp); temp.pop_back(); while(j<nums.size()&&nums[j]==nums[i]){j++;} f(nums,result,j,temp); return; } };