LeetCode78 子集 (C++ 两种解法)

这篇博客介绍了如何使用C++解决LeetCode中的子集(幂集)问题。通过位运算的方法,遍历2^n次,根据二进制码流决定是否选择nums数组中的元素,构建所有可能的子集。文章提供了详细的解题思路,并解释了位运算在解决此问题中的作用,以及代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

说明:解集不能包含重复的子集。

示例:

输入: nums = [1,2,3] 输出: [ [3], [1], [2], [1,2,3], [1,3],
[2,3], [1,2], [] ]

参考算法:
(按位与操作)
https://blog.youkuaiyun.com/qq_32805671/article/details/82180036
第一次使用位运算的方法解题,对于本题,采用位运算的方法真的很方便。若nums的长度为n,则遍历2n2n次,每次得到一个子集:

将i看成二进制码流,判断j位是0还是1,如果为1,则选中nums[j]添加到子集中,从而得到一个子集vec
将子集vec保存进res
返回res

 class Solution { public:
        vector<vector<int>> subsets(vector<int>& nums) {
           vector<vector<int>> res;
            if(nums.empty())
                return res;
            res.push_back({});
            int  n = nums.size();
            for(int i = 0; i < n; i++)
            {
                
                int nRes = res.size();
                for(int j = 0; j < nRes; j++)
                {
                    vector<int> temp = res[j];
                    temp.push_back(nums[i]);
                    res.push_back(temp);
                }
            }
            return res;
        } };

其中,不理解之处为:all = 1<<n
朋友解释说是1向左移n位,得到结果为2的n次方,即子集个数;
所以i即为结果中的第i个元素,
尝试了一下输出i,j 和nums[j],结果如下:

i = 0 , j = 0
i = 0 , j = 1
i = 0 , j = 2
i = 1 , j = 0
1
i = 1 , j = 1
i = 1 , j = 2
i = 2 , j = 0
i = 2 , j = 1
2
i = 2 , j = 2
i = 3 , j = 0
1
i = 3 , j = 1
2
i = 3 , j = 2
i = 4 , j = 0
i = 4 , j = 1
i = 4 , j = 2
3

等等~
1<<j ,分别等于0001(j=0), 0010(j=1), 0100(j=2)
i&j!=0,即表示第i个元素中包含nums[j];
即i=0时,vec= {};
i = 1时, vec= {1};
i = 2时, vec= {2};
i = 3时, vec= {1,2};
以此类推。

刚开始不理解这种思路,不过仿照这个输出,有了自己的思路:
若nums = { }, 则res = { };
若nums = {1},则res= {{},{1}};
同理,若nums中每新增一个元素,即res中元素个数为原来二倍,新增子集为原来基础上每个子集中增加新增的元素。
代码如下:

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
       vector<vector<int>> res;
        if(nums.empty())
            return res;
        res.push_back({});
        int  n = nums.size();
        for(int i = 0; i < n; i++)
        {
            
            int nRes = res.size();
            for(int j = 0; j < nRes; j++)
            {
                vector<int> temp = res[j];
                temp.push_back(nums[i]);
                res.push_back(temp);
            }
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值