这个是在补之前的题。这道题就是让你输出一个无重复数字的序列的全部子集,听起来hin简单,但是我却想不出来怎么做。看了题解之后两种方法都很简单,但是我自己又不会写。
方法一:每一个数字有取和不取两种状态,想到了什么?二进制。于是每次+1就可以枚举出所有情况
class Solution {
public:
vector<int> t;
vector<vector<int>> ans;
vector<vector<int>> subsets(vector<int>& nums) {
int n = nums.size();
for (int mask = 0; mask < (1 << n); ++mask) {
t.clear();
for (int i = 0; i < n; ++i) {
if (mask & (1 << i)) {
t.push_back(nums[i]);
}
}
ans.push_back(t);
}
return ans;
}
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/subsets/solution/zi-ji-by-leetcode-solution/
这是LeetCode官方题解上的代码,用到了位运算【呜呜呜呜我一点都不会,都是以前有能用位运算的解法偷懒没好好学】
x << n
表示将x化为二进制表示,然后左移n位,也就是在右边添上n个零,也就相当于x乘2的n次方。第一层循环的意思大家应该能意会吧。
第二层循环这个实现非常妙。我们现在需要做的是看看哪一位是1,然后把对应位置的数字放到t里。这里用了一个mask & (1 << i)
,i是从1到nums.size()的。我们就能看出来1<<i
就是依次把每一位放上1(比如001、010、100),然后再与我们枚举的mask做&操作,看看mask有哪些位是1
位运算真的太妙了呜呜呜呜我一定要好好学
我之前想用bitset来完成十进制到二进制的转换,然后再套个循环看看哪一位是1就行了,但是bitset和数组一样,大小得是个常数,所以这道题应该是就不好用了。
方法二:递归
class Solution {
public:
void solve(vector<vector<int>> &ans, int cnt, vector<int> res, vector<int> nums)
{
if (cnt == nums.size())
{
ans.push_back(res);
return;
}
res.push_back(nums[cnt]);
solve(ans, cnt + 1, res, nums);
res.pop_back();
solve(ans, cnt + 1, res, nums);
}
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> ans;
vector<int> res;
solve(ans, 0, res, nums);
return ans;
}
};
完了我怎么看每道题都大有文章_(:з」∠)_这说明我啥也不会啊
我一开始写不出来的原因是我想,枚举第一位,选,ans.push_back(res)
,不选,ans.push_back(res)
,第二位,……这样的话就会出现0、00、000、1、10、100……
实际上还是要等整个序列枚举完了,到头了才能放进ans
【我怎么有这么多奇奇怪怪的错误啊呜呜呜呜】