Given a set of distinct integers, nums, return all possible subsets.
Note:
- Elements in a subset must be in non-descending order.
- The solution set must not contain duplicate subsets.
For example,
If nums = [1,2,3]
, a solution is:
[ [3], [1], [2], [1,2,3], [1,3], [2,3], [1,2], [] ]Array Backtracking Bit Manipulation
Solution in C++1:
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> result;
if(nums.size()==0) return result;
sort(nums.begin(), nums.end());
vector<int> levelResult;
getSubsets(nums, 0, levelResult, result);
return result;
}
void getSubsets(vector<int>& nums, int height, vector<int> curResult, vector<vector<int>>& result){
if(height==nums.size()){
result.push_back(curResult);
return;
}else{
getSubsets(nums, height+1, curResult, result);
curResult.push_back(nums[height]);
getSubsets(nums, height+1, curResult, result);
}
}
};
Note:
基于深度优先遍历的递归。根据nums数组构建一棵树,根到叶子的路径代表nums[0]到nums[len-1]的状态。左分支表示该数字加入集合,右分支表示该数字不加入集合。每个叶子结点为一个结果,所有叶子结点的集合猥琐求结果。所以用DFS递归思想求得所有叶子结点。
Solution in C++ 2:
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> result;
if(nums.size()==0) return result;
sort(nums.begin(), nums.end());
for(int i=0; i<nums.size(); i++){
getSubsets(nums, i, result);
}
vector<int> emp;
result.push_back(emp);
return result;
}
void getSubsets(vector<int>& nums, int index, vector<vector<int>>& result){
int curSize = result.size();
for(int i=0; i<curSize; i++){
vector<int> cur = result[i];
result[i].push_back(nums[index]);
result.push_back(cur);
}
vector<int> single;
single.push_back(nums[index]);
result.push_back(single);
}
};
Note:
只要我们能找到比原问题规模小却同质的问题,都可以用递归解决。比如要求{1, 2, 3}的所有子集,可以先求{2, 3}的所有子集,{2, 3}的子集同时也是{1, 2, 3} 的子集,然后我们把{2, 3}的所有子集都加上元素1后(注意排序),又得到同样数量的子集, 它们也是{1, 2, 3}的子集。这样一来,我们就可以通过求{2, 3}的所有子集来求 {1, 2, 3}的所有子集了。即为求1,2,3的子集,要先求2,3的子集,然后再把1加入到2,3的子集中去,典型的递归思路。代码如下:
reference from http://www.tuicool.com/articles/J3En2e
其实就是每次有一个新数,就把它加到已经存在的所有子集的后面。记得每次在循环里把只包含这个数本身的子集添加进去。而且每次在已存在的子集后面添加新数形成新子集时,别忘了要把修改前的子集重新添加到result里,因为之前的子集必然也是一个合法的subset。还有记得最后在结果里添加上空子集。
Solution in C++ 3:
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> result;
if(nums.size()==0) return result;
sort(nums.begin(), nums.end());
<span style="white-space:pre"> //n个数有0~max-1即2^n中组合,1<<n表示2^n</span>
int max = 1<<nums.size();
for(int i=0; i<max; i++){
vector<int> cur;
int index = 0, bound = i;
while(bound>0){
if(bound&1)
cur.push_back(nums[index]);
bound>>=1;
index++;
}
result.push_back(cur);
}
return result;
}
};
Note:
求子集问题就是求组合问题。数组中的n个数可以用n个二进制位表示,当某一位为1表示选择对应的数,为0表示不选择对应的数。