[CareerCup 8.3] 求一个集合的所有子集

这是一个很经典的问题,相对来说,也是比较简单的问题。首先,通过数学知识我们知道一个含n个元素的集合一共有2^n个子集。

方法1:采用递归的方法

举个例子来说{a, b, c}
我们可以先求{b, c}的所有子集{}, {b}, {c}, {b, c}
然后将{b, c}的所有子集与a进行组合与{b, c}的所有子集一起,形成{a, b, c}的所有子集
{}, {b}, {c}, {b, c}, {a}, {a, b}, {a, c}, {a, b, c}

代码如下:

 

/**
求一个集合的所有子集
我们可以递归来考虑这个问题
举个例子来说{a, b, c}
我们可以先求{b, c}的所有子集{}, {b}, {c}, {b, c}
然后将{b, c}的所有子集与a进行组合与{b, c}的所有子集一起,形成{a, b, c}的所有子集
{}, {b}, {c}, {b, c}, {a}, {a, b}, {a, c}, {a, b, c}
**/
vector<set<int>> subset(set<int> s)
{
	if (s.empty())
		return vector<set<int>>();
	int b = *s.begin();
	s.erase(s.begin());
	vector<set<int>> v = subset(s);
	vector<set<int>> result;
	set<int> t;
	result.push_back(t);
	t.insert(b);
	result.push_back(t);
	for (vector<set<int>>::iterator it = v.begin(); it != v.end(); it++)
	{
		if (! it->empty())
		{
			set<int> n(*it);
			n.insert(b);
			result.push_back(*it);
			result.push_back(n);
		}
	}
	return result;
}

 

方法2:从二进制的观念来考虑

注意一个n个元素的集合有2^n个子集
比如一个集合{a,b,c}有8个子集
注意到求子集的时候,有个特点,我们就只要确定一个元素是否在子集中
比如所有的元素都不在子集中,那么这个子集为空集
如果所有的元素都在子集中,那么这个子集为这个集合本身
对于一个n个元素,可以用n位2进制来表示
比如{a, b, c}可以用3位2进制表示
0 000 {}
1 001 {a}
2 010 {b}
3 011 {a, b}
4 100 {c}
5 101 {a, c}
6 110 {b, c}
7 111 {a, b, c}

这种算法有一个问题,就是当集合的大小超过32后,就会溢出,但是考虑一下2^32个结果也基本上存不下了。

代码如下:

 

/**
注意一个n个元素的集合有2^n个子集
比如一个集合{a,b,c}有8个子集
注意到求子集的时候,有个特点,我们就只要确定一个元素是否在子集中
比如所有的元素都不在子集中,那么这个子集为空集
如果所有的元素都在子集中,那么这个子集为这个集合本身
对于一个n个元素,可以用n位2进制来表示
比如{a, b, c}可以用3位2进制表示
0 000 {}
1 001 {a}
2 010 {b}
3 011 {a, b}
4 100 {c}
5 101 {a, c}
6 110 {b, c}
7 111 {a, b, c}
**/
vector<set<int>> subset_two(set<int> s)
{
	int count = s.size();
	int i, j;
	vector<set<int>> v;
	for (i = 0; i < 1 << count; i++)
	{
		set<int> t;
		j = 0;
		for (set<int>::iterator it = s.begin(); it != s.end(); it++)
		{
			if (get_bit(i, j++))
				t.insert(*it);
		}
		v.push_back(t);
	}
	return v;
}

 

测试代码:

 

int main()
{
	set<int> s;
	s.insert(1);
	s.insert(2);
	s.insert(3);
	vector<set<int>> v = subset_two(s);
	for (vector<set<int>>::iterator it = v.begin(); it != v.end(); it++)
	{
		for (set<int>::iterator sit = it->begin(); sit != it->end(); sit++)
			cout << *sit << ' ';
		cout << endl;
	}
	return 0;
}

 

posted on 2011-12-22 22:41  小橋流水  阅读(283)  评论(0编辑  收藏  举报

导航