【问题描述】
{},
{a}, {b}, {c}, {d},
{a, b}, {a, c}, {a, d}, {b, c}, {b, d}, {c, d},
{a, b, c}, {a, b, d}, {a, c, d}, {b, c, d},
{a, b, c, d}
一共16个,事实上n个元素的集合的子集共有2n个(包含空集)。
【方法一】递归
定义一个元素数组mark[ ],用来存放第i个元素,当第i个元素不出现在子集中,对应的位置为空。伪代码如下:
共n个元素,每个元素取或不取,
subset(判断第i个元素)
{
若i是最后一个元素(i>=n):
连续输出mark数组中的所有值,空的不打印,返回。
否则:
不取第i个元素,
subset(判断第i+1个数)
取第i个元素,
subset(判断第i+1个数)
}
【方法二】位操作
集合set={a,b,c,d},对于任意一个元素,在每个子集中,要么存在,要么不存在,对应关系是:
a->1或a->0
b->1或b->0
c->1或c->0
映射为子集:
(a,b,c)
(1,1,1)->(a,b,c)
(1,1,0)->(a,b )
(1,0,1)->(a, c)
(1,0,0)->(a )
(0,1,1)->( b,c)
(0,1,0)->( b )
(0,0,1)->( c)
(0,0,0)->@ (@表示空集)
void findSubset(char *array,int len) {
int mask,index;
int subset_len = 1 << len;//2^len
for (int i = 0; i < subset_len; i++) {
mask = i;
index = 0;
while (mask){
if (mask & 1)
cout << array[index];
mask >>= 1;
++ index;
}
cout <<endl;
}
}
当然还要输出空集,上面的代码省略了这一行。