您的位置:首页 > 其它

求一个集合的所有子集

2013-06-09 09:22 211 查看
《cracking the coding interview》第8.3节

例如,对于集合S={a,b} ,子集有 { },{a},{b},{a,b} 四种。

对于集合S,

 分类方法1,分为元素个数为0,1,2...s (s 为集合的所有元素个数)种,计算比较复杂;

 分类方法2,每个元素出现或者不出现,有2^n 个字集合。

 思路是:首先子集为{},然后添加一个元素a,集合为{},{a}; 然后添加一个元素b,集合为{b},{b,a}; 前面的加起来就是所求集合。

代码为:

vecs 表示向量的向量,及保存之前的集合,more表示构成的新集合

void f(int *A,int n){
vector<vector<int> > vecs;
vector<int> more;
vecs.push_back(more);
for(int i=0;i<n;i++){
int size=vecs.size();
for(int j=0;j<size;j++){
vector<int> iter=vecs[j];
vector<int> temp;
for(int k=0;k<iter.size();k++){
temp.push_back(iter[k]);
}
temp.push_back(A[i]);
vecs.push_back(temp);
}
}
int count=0;
for(i=0;i<vecs.size();i++){
vector<int> iter=vecs[i];
for(int k=0;k<iter.size();k++){
cout<<iter[k]<< " ";
}
cout<<endl;
count++;
}
cout<<"count="<<count<<endl;
}

 方法3:

然而我们发现的一个事实是,所有元素或者出现或者不出现,就如计算中的数字,或者0或者1,这是一个 启发。也就是说2^n种子集,其实可以表示为一:2^n 长度的二进制序列,其中每个位出现一次1。

比如 三个数{a,b,c} 可以用一个三位二进制表示 000,001,010,011,100,101,110,111,其中每个组合中的1代表对应元素的组合。

void f2(int *A,int n){
int *p=new int
;
int p_i=0;
int max=1<<n;
int count=0;
for(int i=0;i<max;i++){
int k=i;
int index=0;
p_i=0;
while(k>0){
if((k&1)>0){
p[p_i++]=A[index];
}
k>>=1;
index++;
}
for(int j=0;j<p_i;j++){
cout<<p[j]<<" ";
}
count++;
cout<<endl;
}
cout<<"count="<<count<<endl;

}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: