LeetCode | 78. 子集
给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例:
输入: nums = [1,2,3]
输出:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
在它们的指数级解法中,要确保生成的结果 完整 且 无冗余,有三种常用的方法:
- 递归
- 回溯
- 基于二进制位掩码和对应位掩码之间的映射字典生成排列/组合/子集(位运算)
位运算解法:
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>>ret;
ret.push_back({});//压入空集
int size = nums.size();
int subsize = pow(2,size);
int hash = 1;
while(hash < subsize){
vector<int>temp;
for(int k = 0;k<size;++k){
int a = 1<<k;
if(a&hash){
temp.push_back(nums[k]);
}
}
ret.push_back(temp);
++hash;
}
return ret;
}
};
原理:
数组元素个数 为 3 ,那么 全部子集有 $2^3 = 8 $个, 使用位图表示,其中 位为 1 表示数组下标对应的位置。
0 0 0 => { } //但要注意一下,这里我们是以 a = 1 << k 的所以并不会直接压空集进集合中
0 0 1 => { 1 }
0 1 0 => { 2 }
0 1 1 => { 1, 2}
1 0 0 => { 3 }
1 0 1 =>{1 , 3}
1 1 0 => {2 , 3}
1 1 1 =>
递归解法:
class Solution {
public:
vector<vector<int>> result;
vector<vector<int>> subsets(vector<int>& nums) {
vector<int> tmp(nums.size(), 0);
subsets(nums, tmp, 0, 0);
return result;
}
void subsets(vector<int>& nums, vector<int>& tmp, int pos, int t_pos) {
if (pos >= nums.size()) {
result.emplace_back(vector<int>(tmp.begin(), tmp.begin()+t_pos));
return;
}
tmp[t_pos] = nums[pos];
subsets(nums, tmp, pos + 1, t_pos+1); // 取nums[pos]
subsets(nums, tmp, pos + 1, t_pos); // 不取nums[pos]
}
};
回溯解法:
/*
to be continue;
*/