【Hot 100】78. 子集

请添加图片描述

  • 🙋‍♂️ 作者:海码007
  • 📜 专栏:算法专栏
  • 💥 标题:【Hot 100】78. 子集
  • ❣️ 寄语:书到用时方恨少,事非经过不知难!

引言

子集

  • 🎈 题目链接:
  • 🎈 做题状态:

我的解题

和上一道全排列的题目有异曲同工之处,都是使用回溯。只不过这个子集,每一层要采用一个起始索引来标识遍历的范围。

class Solution {
public:
    void backtrace(vector<vector<int>>& res, vector<int>& path, const vector<int>& nums, int sIndex)
    {
        res.emplace_back(path);
        if (sIndex == nums.size()) return;

        for (int i = sIndex; i < nums.size(); ++i)
        {
            path.emplace_back(nums[i]);
            backtrace(res, path, nums, i+1);
            path.pop_back();
        }
    }

    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>> res;
        vector<int> path;
        backtrace(res, path, nums, 0);
        return res;
    }
};

代码优化

✅ 优点分析

  1. 回溯思路正确:你正确地使用了一个 sIndex 起始索引,避免重复选择,满足子集的非重复性要求。
  2. 结果收集时机合理:在每次进入递归就收集当前 path,因为子集允许任意长度(包括空集)。
  3. 变量命名清晰、可读性好

🧠 可优化建议

sIndex == nums.size() 的判断其实可以省略

即使当前 sIndex == nums.size(),下面的 for 循环也不会执行,所以你写的:

if (sIndex == nums.size()) return;

可加可不加 的,主要取决于你是否想显式表达“到头了就返回”。如果去掉它,代码更简洁且不会影响结果:

res.emplace_back(path);  // 永远在进入递归时记录一次
for (int i = sIndex; i < nums.size(); ++i) {
    path.emplace_back(nums[i]);
    backtrack(res, path, nums, i + 1);
    path.pop_back();
}

✅ 完整优化建议版本

class Solution {
public:
    void backtrack(vector<vector<int>>& res, vector<int>& path, const vector<int>& nums, int sIndex) {
        res.emplace_back(path);
        for (int i = sIndex; i < nums.size(); ++i) {
            path.emplace_back(nums[i]);
            backtrack(res, path, nums, i + 1);
            path.pop_back();
        }
    }

    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>> res;
        vector<int> path;
        backtrack(res, path, nums, 0);
        return res;
    }
};

🧩 与全排列的核心区别

特性全排列子集
是否允许重复选择
是否使用 used[]
回溯终止条件path.size() == nums.size()每次进入递归就收集 path
是否收集不同长度否(只有完整)是(所有)
起始位置控制不需要(所有数字都可选)需要(避免重复)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值