使用二进制数枚举子集

来源:互联网 发布:淘宝网羽绒服半成品 编辑:程序博客网 时间:2024/06/08 02:33

问题描述:枚举给定集合的所有子集,包括只含一个元素的集合以及给定集合本身。当集合中出现值相同的元素时,根据不同性质可将子集分为:

  • 允许重复包含相同值的元素
  • 不允许重复包含相同值的元素

思路:利用二进制的“开关”特性枚举,具体为:假设给定集合A大小为n,则想象A = {a[0], a[1], ..., a[n-1]}的每个元素对应一个开关位(0或1),0表示不出现,1表示出现。当每个元素的开关位的值确定时,就得到一个子集,因此共有2^n-1种情况(全0为空集,这里不考虑)。我们利用区间[1, 2^n-1],该区间上的每一个整数对应一个子集,对应方法是遍历该整数二进制表示的每一位,若该位为1则相应子集中存在对应元素,否则不存在。

需要注意的是:对于上述第一种子集,二进制法可直接使用;而对于第二种子集,使用二进制法之前需要先对集合进行“去重”(可利用hash表去重)

代码

void process(int a[], int n){for(int i = 1; i < (1<<n); i++){  //1<<n相当于2^n,i表示区间中的某一个整数for(int j = 0; j < n; j++){  //用j遍历区间中每一个整数的每一位if((i>>j)&0x01 == 0x01)  //该为为1,对应元素a[j]存在printf("%d ", a[j]);}printf("\n");}}
0 0
原创粉丝点击