1. 题目
Given a collection of integers that might contain duplicates, nums, return all possible subsets.
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],
[]
]
2. 思路
从前往后遍历,保留下当前已经计算好的组合集合。对当前i号元素的加入,就是有i和没有i的场景。没有i的场景就是已有的集合。有i的就是对已有的集合追加上i后的集合。两个的并集就是加入i之后的结果。
如果i和上一个元素是重复的,则只需要考虑i-1加入过集合的那部分子集。对于不包含i-1元素的场景来说,这部分子集加入i的结果集,和已有的加入过i-1的结果集是重复的。所有跳过这部分就可以了。
3. 代码
耗时:9ms
class Solution {
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
vector<vector<int>> subsets;
sort(nums.begin(), nums.end());
subsetsWithDup(nums, 0, subsets);
return subsets;
}
void subsetsWithDup(vector<int>& nums, int start, vector<vector<int>>& subsets) {
vector<int> emp;
subsets.push_back(emp); // 初始化第一个空元素
int last_idx = 0;
for (int i = 0; i < nums.size(); i++) {
// 对于非重复元素,直接考虑nums[i]没有和有的两种场景即可
// 没有即为先有的subsets结果,有时对现有的结果追加nums[i]后组合的新结果
int start_idx = 0;
if (i > 0 && nums[i] == nums[i-1]) {
// 对于重复元素,则从上次追加过的点开始
start_idx = last_idx;
}
int cur_sz = subsets.size();
last_idx = cur_sz;
for (int j = start_idx; j < cur_sz; j++) {
vector<int> one = subsets[j];
one.push_back(nums[i]);
subsets.push_back(one);
}
}
}
};