子集:
给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例:
输入: nums = [1,2,3]
输出:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
思路1:
刚开始写的时候想着按照子集中元素个数枚举,这样就可以沿用77.组合的思路求解。
代码如下:
class Solution {
public:
vector<vector<int>> res;
void dfs(int index, int n, int k, vector<int>& temp, vector<int>& nums){
if(k == 0){
res.push_back(temp);
return;
}
for(int i = index; i < n - k + 1; i++){
temp.push_back(nums[i]);
dfs(i + 1, n, k-1, temp, nums);
temp.pop_back();
}
}
vector<vector<int>> subsets(vector<int>& nums) {
res.clear();
res.push_back({});
int n = nums.size();
if(n == 0) return res;
res.push_back(nums);
for(int i = 1; i < n; i++){ //按子集中元素个数顺序计算
vector<int> temp;
dfs(0, n, i, temp, nums); //计算所有含有i个元素的组合
}
return res;
}
};
很明显这个算法把题目做复杂了,回溯的复杂度为O(i * C(n,i)),i又从1到n求和;
思路2:
换个思路,其实这就是一个数学题,对每一个元素无非是选与不选两个操作,用二进制表示就是0011这样的一串数,于是所有情况就是从00…00 到 11…11
代码如下:
class Solution{
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> res;
for(int i = 0; i < (1<<nums.size()); i++){ //位运算
vector<int> temp;
for(int j = 0; j < nums.size(); j++){
if(((i>>j) & 1) == 1) temp.push_back(nums[j]);
}
res.push_back(temp);
}
return res;
}
};
思路3:
其实一个数选与不选还可以这样想,如果选就代表多了:在已存储的子集中加入这一元素而产生的新集合。
注:空集合是初始情况
代码如下:
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> res;
res.push_back({});
int n = nums.size();
for(auto c:nums){
int size = res.size();
for(int i = 0; i < size; i++){
vector<int> temp = res[i];
temp.push_back(c);
res.push_back(temp);
}
}
return res;
}
};
思路4:
另外还看到一种用二叉树形象表示所有情况的解法:点击链接查看
思路就是用左子树表示不选,右子树表示选,等到达树底部的时候就得到了一个子集
代码如下:
class Solution{
public:
void preOrder(vector<int>& nums, int i, vector<int> subset, vector<vector<int>>& res) {
if(i == nums.size()){ //到达树底时记录
res.push_back(subset);
return;
}
subset.push_back(nums[i]); //这里用左子树代表选第i个数
preOrder(nums, i + 1, subset, res);
subset.pop_back();
preOrder(nums, i + 1, subset, res);
}
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> res;
vector<int> temp;
preOrder(nums, 0, temp, res);
return res;
}
};