子集生成,给定一个数组,数组中包含一些元素(简单起见,假设其中包含的是数字)
生成该集合所有的子集。
比如:{1, 2, 3}
子集为{{}, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}}
本题比较简单,有点像01背包问题。解题思路如下:
首先,将空集合放入结果集。然后遍历源集合中的每个元素,往空集合中加还是不加。话说不太明白,举个例子
{a, b, c}
首先结果集合中添加{}空集合
然后将结果集中的元素去除,对第一个源集合中的元素,也就是a,进行选择,添加到{}中就变为{a}, 不添加就是{}, 然后将这两个结果,添加到最终结果中去,此时最终结果集合中的元素为{{},{a}}。
按照上面的步骤,将{}, {a}取出,处理b,对于{}来说,有添加进去和不添加进去,分别为{}, {b},对于{a}来说也一样有添加和不添加,结果为{a}, {a, b},最后将这四个结果添加进结果集合,此时结果集合变为{{},{b}, {a}, {a, b}}
重复上述思想,即可求得结果
如果还不是太清楚怎么操作分析代码是最好的办法:
我分别采用了递归、迭代和二进制解决此题。
// 递归
set<set<int>> helper1(const vector<int> &src, int cur){//cur当前处理节点的index,从后往前处理,因为是递归,先拿到[]集合
if(0 == cur){
set<set<int>> finalSet;
finalSet.insert(set<int>());
set<int> tempSet;
tempSet.insert(src[cur]);
finalSet.insert(tempSet);
return finalSet;
}
set<set<int>> newSet_ = helper1(src, cur - 1);
set<set<int>> newSet = newSet_;
for(auto eachSet : newSet){
eachSet.insert(src[cur]);
newSet.insert(eachSet);//加
}
return newSet;
}
// 迭代
set<set<int>> helper2(const vector<int> &src){
set<set<int>> finalSet;
finalSet.insert(set<int>());//首先将空集合加进去
for(int a : src){
set<set<int>> tempDup = finalSet;
for(auto each : tempDup){
each.insert(a);//加
finalSet.insert(each);
}
}
return finalSet;
}
// 二进制
set<set<int>> helper3(const vector<int> &src){
set<set<int>> finalSet;
int size = src.size();
for(int i = pow(2, size) - 1; i >= 0; --i){//111到000
//对每一个都左移size次
set<int> midRes;
int index = 0;
while(index < size){
if(i&(1<<index)){
midRes.insert(src[index]);//index表示某位为1时,拿到该下标的元素
}
++index;
}
finalSet.insert(midRes);
}
return finalSet;
}
int main(){
vector<int> src{1, 2};
// set<set<int>> res = helper1(src, src.size() - 1);
// set<set<int>> res = helper2(src);
set<set<int>> res = helper3(src);
for(auto each : res){
if(each.empty()){
cout<<"nil"<<endl;
continue;
}
for(int a : each){
cout<< a <<" ";
}
cout<< endl;
}
return 0;
}
说明一下二进制:
A B C
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
其中1表示选择对应的元素,0表示不选,再结合代码很容易想到处理思路。
写的比较匆忙,如有问题还望指正!
除二进制外,可以抽象为对每个元素选还是不选,所以可以在构造一个选与不选的树,如下图
代码如下:
leetcode链接
class Solution {
public:
vector<vector<int>> ans;
void helper(vector<int>& nums, vector<int> &res, int index){
if(index >= nums.size()){
ans.push_back(res);
return;
}
// 不选
helper(nums, res, index + 1);
// 选
res.push_back(nums[index]);
helper(nums, res, index + 1);
res.pop_back();
}
vector<vector<int>> subsets(vector<int>& nums) {
vector<int> res;
helper(nums, res, 0);
return ans;
}
};