使用二进制数枚举子集

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

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

思路:利用二进制的“开关”特性枚举,具体为:假设给定集合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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值