转载自:http://hawstein.com/posts/8.3.html
Write a method that returns all subsets of a set.
这道题印象中看过好多次,但是总是做不出来,今天想了下。
参考博客,总结下。
两种解法:
1.将一个数组中的数出现在子集中为1,不出现为0来表示,总共是有2^n个子集。这样子就归结为判断一个数某一位上是否有1,有的话,将对应下标的数组元素插入到子集中,循环完,即数字到了2^n的时候结束。
typedef vector<vector<int> > vvi; typedef vector<int> vi; vvi get_subsets(int a[], int n){ //O(n2^n) vvi subsets; int max = 1<<n; for(int i=0; i<max; ++i){ vi subset; int idx = 0; int j = i; while(j > 0){ if(j&1){ subset.push_back(a[idx]); } j >>= 1; ++idx; } subsets.push_back(subset); } return subsets; }
2.将它理解为递归的过程,{1,2,3}的子集相当于在{2,3}的子集基础上加上{1},所以一直递归到数据集为空。数据集为空,对应空子集,然后返回。得到了后续元素的子集后,在这个基础上插入现在这个位置的元素,得到所有的子集。
vvi get_subsets1(int a[], int idx, int n){
vvi subsets;
if(idx == n){
vi subset;
subsets.push_back(subset); //empty set
}
else{
vvi rsubsets = get_subsets1(a, idx+1, n);
int v = a[idx];
for(int i=0; i<rsubsets.size(); ++i){
vi subset = rsubsets[i];
subsets.push_back(subset);
subset.push_back(v);
subsets.push_back(subset);
}
}
return subsets;
}
这道题,表明,我对递归的思路还不是很熟悉,另外第一个想法很犀利。数学的厉害!!