给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集不能包含重复的子集。你可以按任意顺序返回解集。
示例 1:
输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
示例 2:
输入:nums = [0]
输出:[[],[0]]
关于顺序
法一:递归枚举,对每个元素都进行选或不选
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> result;//记录最终结果
vector<int> path;//记录每趟子集计算中的当前子集
subsets(path, nums,0, result);//初始从第一个数字开始选
return result;
}
void subsets(vector<int>& path, vector<int>& nums, int cur,vector<vector<int>> &result)
{
//如果判断完所有的数字就把当前子集加入结果中
if(cur==nums.size())
{
result.push_back(path);
return;
}
//如果不选当前数字
subsets(path,nums,cur+1, result);
//如果选择当前数字
path.push_back(nums[cur]);
subsets(path,nums,cur+1,result);
path.pop_back();//把path数组恢复原样
}
};
时间复杂度:O(2^n)
空间复杂度O(n)
思路
法二:位向量法,递归枚举,使用bool数组记录选择
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> result;//记录结果
vector<bool> selected(nums.size(),false);//记录是否使用当前数字
subsets(selected, nums,0, result);
return result;
}
//依次对每个数字做选择,全部数字选择完后将子集记录到结果中
void subsets(vector<bool>& selected, vector<int>& nums, int cur,vector<vector<int>> &result)
{
if(cur==nums.size())//记录当前子集
{
vector<int> path;
//将selected中的数据转化为当前子集
for(int i=0;i<nums.size();i++)
if(selected[i]==true) path.push_back(nums[i]);
result.push_back(path);
return;
}
selected[cur] = true;//选择当前数字,递归调用挑选下一个数字
subsets(selected,nums,cur+1, result);
selected[cur] = false;//不选择当前数字,递归调用挑选下一个数字
subsets(selected,nums,cur+1,result);
}
};
时间复杂度:O(2^n)
空间复杂度O(n)
该方法只能在没有重复数字时使用
法三:二进制法,即位向量法的迭代版
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> result;
vector<int> subset;
int n=nums.size();
for(int i=0; i<(1<<n); i++)//1<
{
for(int j=0; j<n; j++)//依次将每一个int转化为一个子集
{
if(i&(1<<j)) subset.push_back(nums[j]);
}
result.push_back(subset);//子集加入到结果中
subset.clear();//清空当前子集
}
return result;
}
};