题目描述:
给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例:
输入: nums = [1,2,3]
输出:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
解题思路:
解题思路1(包含三种解题方法):这个我没看懂作者本人的解题思路,没看懂树是怎么建的
https://blog.youkuaiyun.com/camellhf/article/details/73551410
因此找到了解题思路2:是对解题思路1中作者的想法的一个详细讲解
https://www.cnblogs.com/ariel-dreamland/p/9154503.html
建立的树是这样的:(来源于第二个链接)
[]
/ \
/ \
/ \
/ \
/ \
[1] []
/ \ / \
/ \ / \
[1 2] [1] [2] []
/ \ / \ / \ / \
[1 2 3] [1 2] [1 3] [1] [2 3] [2] [3] []
第一层为空集,第二层为对第一个数的选择,以此类推。左节点代表选中,右节点代表不选。
代码:
方法1:用dfs解决,对应解题思路1的第一个方法
注意的点:
1.每次一个数字出栈就相当于选择了不选择它的路。
2.为什么从第一层开始循环?因为根节点不存在不选择它的情况。
3.为什么不需要存储不选择的情况?因为在存储上一层节点值的时候,实际上就是在存储不选择的情况,因为没到下一层相当于没选择。
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> result;
vector<int> tmp;
//sort(nums.begin(), nums.end());
getSub(nums,result,0,tmp);
return result;
}
void getSub(vector<int> s,vector<vector<int>> &result,int layer,vector<int> &tmp)
{
result.push_back(tmp);
for(int i = layer;i < s.size();i++)
{
tmp.push_back(s[i]);
getSub(s,result,i + 1,tmp);
tmp.pop_back();
}
}
};
方法2:用bitmap解决,对应解题思路1的第二个方法
感觉原链接中的代码写的非常棒!
外层循环控制对数组中每个数字的选择,内层循环是从二进制数000到111所有情况的列举。
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
int bNumber = pow(2,nums.size()); //把二进制数转化为十进制 为2^nums.size()
vector<vector<int>> result(bNumber);
for(int i = 0;i < nums.size();i++)
for(int j = 0;j < bNumber;j++)
if(j >> i & 1) //j左移i位(从而判断数组中第i个元素是否加入子集),结果和1相与(从而只取最低位)
result[j].push_back(nums[i]);
return result;
}
};
方法3:对应解题思路1的第三个方法
即:
第二种解法让我很惊叹。它是发掘到了一个规律,集合中每添加一个元素,则子集数目增加一倍,且增加的子集为所有原始子集加上新的元素。举个例子:nums=[1,2,3]
1. 初始时集合为空,子集为[ [] ]。
2. 添加一个元素1,即集合为[1]时,子集为空集和空集+元素1,即[ [], [1] ]。
3. 添加下一个元素2,集合为[1,2],子集除了包含上一步的所有集合还新增了对应集合+元素2的所有集合,即[ [], [1], [2], [1,2]],其中[2]是空集+元素2,[1,2]是[1]+元素2。
4. 添加下一个元素3,集合为[1,2,3],类似的得到子集为[ [], [1], [2], [1,2], [3], [1,3], [2,3], [1,2,3] ],其中[3]是空集+元素3,[1,3]是[1]+元素3,[2,3]是[2]+元素3,[1,2,3]是[1,2]+元素3。
(来源于第一个链接)
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> result;
vector<int> empty;
result.push_back(empty);
for (int i = 0; i < nums.size(); i++)
{
int result_size = result.size();//进入循环前存储在添加前的结果长度 因为添加后长度会变
for (int j = 0; j < result_size; j++)
{
vector<int> tmp = result[j];
tmp.push_back(nums[i]);
result.push_back(tmp);
}
}
return result;
}
};