LeetCode | Subsets II(带有重复数据的数组的子集)


Given a collection of integers that might contain duplicates, S, 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 S = [1,2,2], a solution is:

[
  [2],
  [1],
  [1,2,2],
  [2,2],
  [1,2],
  []
]

题目解析:

这道题目与LeetCode | Subsets 思路一样。只是这道题目中有重复数据。

之前见过这样处理重复数据的。1、2、2、3。当遍历的时候,如果第一个2选择了,第二个2可以选择,可以不选择。如果第一个2没有选择,那么第二个2就一定不要选。同理,如果有连续三个2,只有紧挨着前一个选择了,下面的才有资格选择。

再进一步考虑的话,这也就是m个2里面选择0….m个,一共m个情况。那么我们就通过计数count来判断有多少重复数据。然后往里面添加的个数递增即可。

还有一点小技巧。对于第i个数据,我们递归过程中先选择不添加,然后选择添加,那么就不用再退出最后一个数据了。并且我们用的是tmp临时数组,传递到内部的只是一个备份,没有退出的过程。


代码如下:

#include <iostream>
#include <vector>
#include<algorithm>
using namespace std;

class Solution {
public:
    vector<vector<int> > subsetsWithDup(vector<int> &S) {
        vector<vector<int> >res;
        vector<int> tmp;
        vector<int>::size_type num;
        sort(S.begin(), S.end());
        GenerateSub(res,S,tmp,0);
        return res;
    }
    void GenerateSub(vector<vector<int> >&res,vector<int> &S,vector<int> tmp,vector<int>::size_type index){
        if(index >= S.size()){
            res.push_back(tmp);
            return ;
        }
        int count = 1;
        for(int i = index+1;i < S.size();i++){
            if(S[i] != S[index])
                break;
            count++;
        }
        GenerateSub(res,S,tmp,index+count);
        for(int i = 0;i < count;i++){
            tmp.push_back(S[index+i]);
            GenerateSub(res,S,tmp,index+count);
        }
    }
};


int main()
{

    vector<vector<int> >res;
    Solution tp;
    vector<int> S;
    S.push_back(4);
    S.push_back(1);
    S.push_back(4);

    res = tp.subsetsWithDup(S);

    for(int i = 0;i < res.size();i++){
        if(res[i].size() == 0){
            cout << "$" << endl;
            continue;
        }
        for(int j = 0;j < res[i].size();j++)
            cout << res[i][j] << " ";
        cout << endl;
    }

    return 0;
}

点赞