leetcode 78. 子集 medium
题目描述:
给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例:
输入: nums = [1,2,3]
输出:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
解题思路:
解法1: 常规的dfs。
每次进入dfs,都有两个动作,加这个数和不加这个数,然后进入下一层
解法2: 位运算,迭代
对于一个长度为n的数组,每个数字都有出现与不出现两种情况,所以共有 2^n 种情况,那么把每种情况都转换出来就ok了。
缺点(数组最长32or31位?)
解法3: 另一种想法的dfs。 (记这个解法,为了 90题 子集II更方便)
每一位数都可以是index~nums.size()-1的任意一个(并且因为数组元素无重复,下一层dfs的时候 i+1即可),并且每一层一开始的时候,直接push_back(out), 对应没有的情况。
简单来说对于数组【1,2,3】。
解法1的dfs,遍历的方法是 遍历数 1有or没有, 2有or没有,3有or没有。
解法3的dfs,遍历的方法是: 遍历位置, 同时为了避免出现重复的结果,下一个位置的数只能从前面选中的数之后开始选。
[]
[1]
[1 2]
[1 2 3]
[1 3]
[2]
[2 3]
[3]
解法3代码:
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
if(nums.empty())
return {};
vector<int> out;
vector<vector<int>> res;
dfs(nums,out,res,0);
return res;
}
void dfs(vector<int> &nums,vector<int> &out,vector<vector<int>> &res,int index ){
res.push_back(out);
for(int i=index;i<nums.size();++i){
out.push_back(nums[i]);
dfs(nums,out,res,i+1);
out.pop_back();
}
}
};
解法1代码:
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
if(nums.empty())
return {};
vector<int> out;
vector<vector<int>> res;
dfs(nums,out,res,0);
return res;
}
void dfs(vector<int> &nums,vector<int> &out,vector<vector<int>> &res,int cur){
if(cur==nums.size()){
res.push_back(out);
return;
}
out.push_back(nums[cur]);
dfs(nums,out,res,cur+1);
out.pop_back();
dfs(nums,out,res,cur+1);
}
};
解法2代码:
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
if(nums.empty())
return {};
int len = 1<<(nums.size()); // nums的size不能超过 31 or 32
vector<vector<int>> res;
for(int i=0;i<len;++i){
vector<int> out;
for(int j=0;j<nums.size();++j){
if(i&(1<<j))
out.push_back(nums[j]);
}
res.push_back(out);
}
return res;
}
};