求幂集
位运算
比如我们求{1, 2, 3}的幂集,左边的格子,从上到下分别是0-7.
然后0代表空集,1代表{1},…,7代表{1,2,3}
当然如果数组超过32位要再处理一下。因为int为32位。
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> res;
//子集的长度是2的nums.size次方,这里通过移位计算
size_t total = 1 << nums.size();
for (size_t i = 0; i < total; ++i) {
vector<int> vec;
//num也是从0到7,一个for循环一个数
size_t num = i, idx = 0;
while (num) {
//如果数字num的某一位是1,就将nums对应的那一位的数字添加到集合
if (num & 1)
vec.push_back(nums[idx]);
num >>= 1;
++idx;
}
res.push_back(vec);
}
return res;
}
};
递推
输入 0 -->[[]]
输入 1 -->[[],[1]]
输入 2 -->[[],[1],[2],[1,2]]
输入 3 -->[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
可以获得 递推公式: f(n) = f(n-1) + [i+[num] for i in f(n-1)]
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res = [[],]
if not nums:
return res
for num in nums:
res += [arr+[num] for arr in res]
return res
用python写的很简短。
C++如下
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> res;
res.push_back({});
for(int i=0;i<nums.size();i++)
{
int n=res.size();
for(int j=0;j<n;j++)
{
vector<int> temp(res[j]);
temp.push_back(nums[i]);
res.push_back(temp);
}
}
return res;
}
};
DFS
跟之前发过的一样,面临的永远是选还是不选的问题
当然这个图和下面的例子不太恰当,但思想是一样的。
class Solution {
public:
vector<int>tmp;
vector<vector<int>> res;
int n;
vector<vector<int>> subsets(vector<int>& nums) {
n = nums.size();
dfs(nums,0);
return res;
}
void dfs(vector<int>&num,int loc){
if(loc == n){
res.push_back(tmp);
return;
}
tmp.push_back(num[loc]);
dfs(num,loc+1); //要num[loc]
tmp.pop_back();
dfs(num,loc+1); //不要num[loc]
}
};
比如求{0,1,2}的幂集,res的结果是{{0,1,2},{0,1},{0,2},{0},{1,2},{1},{2},{}}.注意顺序。
前四个有0元素,后四个无0元素。就是要与不要。
回溯(暴力递归)
跟上面类似,也是选与不选的问题。
只不过这个用了个for循环
class Solution {
public:
vector<vector<int>> ans;
void dfs(vector<int>& nums, int index, vector<int>& res) {
ans.push_back(res);
if (index >= nums.size())
return;
for (int i = index; i < nums.size(); i++) {
res.push_back(nums[i]); //要nums[i]之后dfs
dfs(nums, i + 1, res);
res.pop_back(); //不要nums[i],进入下一个for循环,i++
}
}
vector<vector<int>> subsets(vector<int>& nums) {
vector<int> res;
dfs(nums, 0, res);
return ans;
}
};
{1,2,3}的幂集应该是,
{}
第一轮for循环{1,2,3},{1,2}, {1,3},{1}
第二轮for循环{2,3},{2}
第三轮for循环{3}
总结
本篇基本都来源于leetcode点赞很高的解法
前两种方法比较取巧,位运算yyds,递推稍微有点数学功底,都是很好的方法。
后两种感觉类似于一种,就是一个要与不要的问题,去递归。
文章写的很垃圾,多谢各位评论区指正。