Description:
Given a collection of integers that might contain duplicates, nums, return all possible subsets (the power set).
Note: 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],
[]
]
解析:相比Subsets I,如何避免重复的数字会造成重复的子集是这道题解题的关键。用一个例子来阐述我的思路nums = {1, 2, 2};
- 首先一个空集 ret = {{}};
- index = 0(属于非重复数字) 将当前状态下的ret先copy一份tmp,在tmp中每一个成员后面添加nums[index], 循环一次后将tmp添加到ret之后;
- index = 1(属于重复数字) index++直到数组结束或者下一个数不相等为止记录下重复数字次数(没有重复的数字次数为1), 然后copy一份ret传给tmp, 循环给tmp的成员后面添加nums[index](数字重复多少次就循环多少次) , 每次循环结束后将tmp添加到ret之后;
index | ret |
0 | {{}} |
1 | {{}, {1}} |
2 | pass(重复数字为两次) |
3 | {{}{1}{2}{1, 2}{2,2}{1, 2,2}}(tmp后添加2循环两次) |
代码1:递归
class Solution {
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
if(nums.empty()) return vector<vector<int> >(1, vector<int>());
sort(nums.begin(), nums.end(), less<int>());
int count = 0;
int val = nums[0];
while(nums.size() && nums[0] == val)//这里如果不判断nums.size()是否为零的话 会导致越界 出现错误
{
nums.erase(nums.begin());
count++;
}
vector<vector<int> > ret = subsetsWithDup(nums);
vector<vector<int> > tmp(ret);
while(count > 0)
{
for(auto& i : tmp)
i.push_back(val);
ret.insert(ret.end(), tmp.begin(), tmp.end());
count--;
}
return ret;
}
};
代码2:尾递归版本(回溯)
class Solution {
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums)
{
vector<vector<int>> ret(1, vector<int>());
sort(nums.begin(), nums.end());
dfs_subsetsWithDup(nums, ret, 0);
return ret;
}
void dfs_subsetsWithDup(vector<int>& nums, vector<vector<int>>& ret, int index)
{
if(index == nums.size()) return;
vector<vector<int> > tmp(ret);
while(index + 1 < nums.size() && nums[index] == nums[index + 1])
{
for(auto& r: tmp)
r.push_back(nums[index]);
ret.insert(ret.end(), tmp.begin(), tmp.end());
index++;
}
for(auto& r: tmp)
r.push_back(nums[index]);
ret.insert(ret.end(), tmp.begin(), tmp.end());
dfs_subsetsWithDup(nums, ret, index + 1);
}
};
代码3:迭代版本
class Solution {
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums)
{
vector<vector<int>> ret(1, vector<int>());
vector<vector<int>> tmp;
sort(nums.begin(), nums.end());
for(int i = 0, count = 1; i < nums.size(); i++, count++)
{
while(i + 1 < nums.size() && nums[i] == nums[i + 1])
{
++i;
++count;
}
tmp.insert(tmp.end(), ret.begin(), ret.end());
while(count > 0)
{
for(auto&t : tmp)
t.push_back(nums[i]);
ret.insert(ret.end(), tmp.begin(), tmp.end());
count--;
}
tmp.clear();
}
return ret;
}
};