程序员面试金典——9.4集合的子集
Solution1:我的答案
该思路本质上是递归,递归的迭代式写法。之前做过类似的题,这个思路就挺好!
class Subset {
public:
vector<vector<int> > getSubsets(vector<int> A, int n) {
// write code here
sort(A.begin(), A.end()); //将A中元素从小到大排列
vector<vector<int> > res;
if(n == 0)
return res;
vector<int> temp;
res.push_back(temp);//temp是空vector,最后返回结果时要去掉
for(int i = 0; i < A.size(); i++) {
int a = res.size();
for(int j = 0; j < a; j++) {
vector<int> temp1 = res[j];
temp1.push_back(A[i]);
res.push_back(temp1);
}
}
reverse(res.begin(), res.end());
res.pop_back();
for(int i = 0; i < res.size(); i++)
reverse(res[i].begin(), res[i].end());
return res;
}
};
Solution2:
书上还有一种组合数学的思路,感觉也是很棒棒啊!
在构造一个集合时,每个元素有两个选择:在或不在。再有n个元素的集合中,总共有
2n
2
n
个子集,非空子集有
2n−1
2
n
−
1
个,那么每一个子集可以视作一个二进制串。
接着,构造所有子集,就相当于构造所有的二进制数。我们可以迭代访问到
2n
2
n
的所有数字,再将这些数字的二进制表示转换为集合。小事一桩!
注意一点:n个二进制组成的数从小到大是0,1,2…
2n−1
2
n
−
1
,共
2n
2
n
个数,不要想当然,稍微想一想!如
(111)2=7,(000)2=0
(
111
)
2
=
7
,
(
000
)
2
=
0
,只要稍微想一想就行!!!
class Subset {
public:
vector<vector<int> > getSubsets(vector<int> A, int n) {
// write code here
sort(A.begin(), A.end()); //将A中元素从小到大排列
vector<vector<int> > res;
if(n == 0)
return res;
int max = 1 << n;
for(int i = 0; i < max; i++) { //从1到2的n次方
vector<int> temp = getVec(A, i);
res.push_back(temp);
}
reverse(res.begin(), res.end());
res.pop_back();
for(int i = 0; i < res.size(); i++)
reverse(res[i].begin(), res[i].end());
return res;
}
vector<int> getVec(vector<int> &A, int x) {
int index = 0;
vector<int> res;
for(int i = x; i > 0; i >>= 1) {
if(i & 1 == 1)
res.push_back(A[index]);
index++;
}
return res;
}
};