子集生成和组合问题
包含n个元素的集合的子集和二进制数的对应关系:
每个子集对应一个二进制数,这个二进制数中的每个1都对应着这个子集中的每个元素,而且子集中的元素是没有顺序的。
打印n个数中任意m个数的组合,对照子集生成的二进制方法,已经知道一个子集对应一个二进制数,那么一个有k个元素的子集,它对应的二进制数中有k个1,所以将问题转化为查找1的个数为k的二进制数。
如何判断二进制数中1的个数为k?
1.对这个n位二进制数逐位检查,共需要检查n次。
2.另一种方法可以直接定位二进制数中1的位置,跳过中间的0.操作:kk=kk&(kk-1),其功能是消除kk的二进制数的最后一个1,连续进行这个操作,每次消除一个1,直到全部消除为止,操作次数就是1的个数。
此操作可以计算出二进制数中1的个数,具体步骤如下:
(1)用kk=kk&(kk-1)消除kk的最后一个1.
(2)num++;
(3)继续上述操作,直到kk=0;
#include<bits/stdc++.h> using namespace std; void print_set(int n,int k){ for(int i=0;i<(1<<n);i++){ //按位 int num=0,kk=i; while(kk){ kk=kk&(kk-1); //清除kk中最后一个1; num++; //统计1的个数; } if(num==k){ //符合条件 for(int j=0;j<n;j++){ if(i&(1<<j)) cout<<j<<" "; cout<<endl; } } } } int main(){ int n,k; //n:元素的总数量 k:个数为k的子集 cin>>n>>k; print_set(n,k); }