90. Subsets II

来源:互联网 发布:东华软件个股分析 编辑:程序博客网 时间:2024/06/17 22:09

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],  []]

这道题牵扯一点数学知识。

求子集,首先我们来看一个证明:

n=1时 明显有两个子集
假设n=k,k>=2时有2^k个子集
则n=k+1时 
新增加的元素与原来的子集又可构成2^k个子集
故此时总共有2^k+2^k=2^(k+1)个子集
故该命题在n>=2时也成立
故命题正确


集合中的每个元素都有两种可能,在集合或不在集合,好像0和1,那么n个元素构成的子集数目就是2^n。

所以对于重复元素,我们可以把它看成一个特殊元素,举例:1, 2, 2 ,元素2具有不在集合,第一个2在集合中,第二个2在集合中三种可能,但我们把它看成一个元素,理解成一个大“2”。所以,我们要对该特殊元素配备一个计数器,用来计数它的数目。普通元素只加入集合一次就可以了,该特殊元素可以加入多次。

我们对这道题首先需要排序,不然难以找到相同元素。

将计数器count初始化为1,因为任意普通元素也至少要加入集合一次。当重复多次时,++count,下次直接跳过重复元素就可以,因为把它看成了一个整体。

代码如下:

class Solution {public:    vector<vector<int>> subsetsWithDup(vector<int>& nums) {        vector<vector<int>> totalset = {{}};        const int size = nums.size();        sort(nums.begin(), nums.end());    /可不要忘记排序        for(int i=0; i<size; ){            int count = 1;            while(i+count<size && nums[i] == nums[i+count])                ++count;            int prev_size = (int)totalset.size();            for(int j=0; j<prev_size; ++j){                vector<int> vec = totalset[j];                for(int k=0; k<count; ++k){                    vec.push_back(nums[i]);                    totalset.push_back(vec);                }            }            i += count;        }        return totalset;    }};


另外一种思路,回溯法:

先深入进去,没路了再回来。

该方法打印顺序为,以[1, 2, 2]为例:

空, 1, 12,122,2, 22

起始这种方法就和我们最普通的形式差不多,从第一个元素开始,打印长度为1,长度为2,...,然后再从第二个元素继续。。。 

class Solution {public:    vector<vector<int>> subsetsWithDup(vector<int>& nums) {        vector<vector<int>> totalset = {{}};        vector<int> vec;        const int size = nums.size();        sort(nums.begin(), nums.end());        handle_detail(totalset, nums, vec, size, 0);        return totalset;    }private:    void handle_detail(vector<vector<int>>& totalset, const vector<int>& nums,                         vector<int>& vec, const int size, int cur){        for(int i=cur; i<size; ++i){            if(i > cur && nums[i] == nums[i-1])                continue;            vec.push_back(nums[i]);            totalset.push_back(vec);            handle_detail(totalset, nums, vec, size, i+1);            vec.pop_back();        }    }};


0 0
原创粉丝点击