vector<vector<int> > subsetsWithDup(vector<int> &S) {数组
sort(S.begin(), S.end()); // 必须排序函数
set<vector<int> > result;学习
const size_t n = S.size();spa
vector<int> v;xml
for (size_t i = 0; i < 1U << n; ++i) {排序
for (size_t j = 0; j < n; ++j) {递归
if (i & 1 << j)it
v.push_back(S[j]);容器
}变量
result.insert(v);
v.clear();
}
vector<vector<int> > real_result;
copy(result.begin(), result.end(), back_inserter(real_result));
return real_result;
}
2. 递归实现
递归实现比较复杂,首先,为了获得全部不重复的集合,咱们能够这么理解这个问题,把数组当作是不一样球的编号,数组的大小为球的个数,不一样的数字为不一样的球,好比数组【1,1,2】就表明有两个标号为1的球和一个标号为2的球,如今的问题是一共要从中取出x个球,x<=n,组成一个子集,有多少种不一样的子集。咱们能够先把不一样标号的球放到不一样的袋子里,标号为1的球都放到标号为1的袋子里,标号为2的球都放到标号为2的袋子里,以此类推,最后咱们假设获得了m个不一样的带子,里面分别放了若干个球,接着咱们要作的只是从这些袋子里面取x个球,一共有多少种组合就是全部的不重复的子集合数,取的过程当中能够在每一个袋子中取0到这个袋子中的球的个数个球。
先看主函数:
void subSetsNoDup(int a[],int n){
unordered_map<int,int> mymap;
for(int i = 0;i<n;i++){
if(mymap.find(a[i]) != mymap.end())
mymap[a[i]]++;
else
mymap[a[i]] = 1;
}
vector<pair<int,int>> elems;
for(auto i = mymap.begin();i!=mymap.end();i++)
elems.push_back(pair<int,int>(i->first,i->second));
sort(elems.begin(),elems.end());
vector<int> path;
subsets2(elems,0,path);
}
此函数前面部分都在分组和计算袋子中的球的数目,只有最后一个函数subsets2执行了取球的过程,下面看subsets2取球过程:
void subsets2(vector<pair<int,int>>& elems,int step,vector<int>& path){
if(step == elems.size()){
printPath(path);
return;
}
for(int i = 0;i<=elems[step].second;i++){
for(int j = 0;j<i;j++)
path.push_back(elems[step].first);
subsets2(elems,step+1,path);
for(int j = 0;j<i;j++)
path.pop_back();
}
}
step记录的是取到了第几个袋子,当取完因此袋子则返回,path是临时变量,记录的是当前的子集。在每次对某个袋子取球时,能够0到取这个袋子中全部球的个数个。每步取一个袋子,取了一个袋子以后递归取下一个袋子。
本人水平有限,文章有错误的地方欢迎你们指出,有问题也但愿你们可以留言交流,一块儿学习进步