78题是子集I,没有重复数字,本题有重复数字
考虑方式相似,不同的地方就是要去处理那些重复的数字
首先要去想的是:重复的数字在什么地方才能出现?
答:在已经出现过的地方才能出现,在没有出现过的地方只能出现那个领头的数字
因此,代码可以从78题修改至如下:
class Solution {
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
vector<vector<int>> res = {{}};
sort(nums.begin(), nums.end());
int start = 0;
for(int i = 0; i < nums.size(); i++)
{
start = (i && nums[i] == nums[i - 1])?start:0;
int len = res.size();
for(int j = start; j < len; j++)
{
auto tmp = res[j];
tmp.push_back(nums[i]);
res.push_back(tmp);
}
start = len;
}
return res;
}
};
第二种想法
我们去想一下,把重复的数字看成一个整体,然后想一下,它的可能性:都不出现,出现一个,出现两个…出现k个
class Solution {
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
vector<vector<int>> res = {{}};
sort(nums.begin(), nums.end());
for(int i = 0; i < nums.size(); i++)
{
int same = 1;
while(i + 1 < nums.size() && nums[i + 1] == nums[i])
{
same++;
i++;
}
int len = res.size();
for(int j = 0; j < len; j++)
{
auto tmp = res[j];
for(int k = 0; k < same; k++)
{
tmp.push_back(nums[i]);
res.push_back(tmp);
}
}
}
return res;
}
};
第二次写题
class Solution {
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<vector<int>> res = {{}};
int cnt = 1;
for(int i = 0; i < nums.size(); i++)
{
if(i + 1 < nums.size() && nums[i + 1] == nums[i])
{
cnt++;
continue;
}
int len = res.size();
for(int j = 0; j < len; j++)
{
auto tmp = res[j];
for(int k = 1; k <= cnt; k++)
{
tmp.push_back(nums[i]);
res.push_back(tmp);
}
}
cnt = 1;
}
return res;
}
};
第三次写题
这里主要注意的是怎么处理重复的
class Solution {
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<vector<int>> res = {{}};
int len = res.size();
for(int i = 0; i < nums.size(); i++)
{
int start = (i > 0 && nums[i] == nums[i - 1])? len : 0;
len = res.size();
for(int j = start; j < len; j++)
{
auto tmp = res[j];
tmp.push_back(nums[i]);
res.push_back(tmp);
}
}
return res;
}
};