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);
            }
        }
    }
};

knzeus
72 声望28 粉丝

行万里路,读万卷书