LeetCode 78. 子集(Subsets)

78. 子集

📘题目描述

给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

示例 1:

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

示例 2:

输入:nums = [0]
输出:[[],[0]]

💡解题思路:回溯法(Backtracking)

🧠核心思想

  • 子集问题的本质是在每个元素面前做“选”或“不选”

  • 使用回溯法逐步构造出所有可能的组合

  • 使用参数 start 控制从哪里开始选数字,确保不重复、不回头

✅Python 实现 

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        res = []

        def backtrack(start, path):
            res.append(path[:])
            for i in range(start, len(nums)):
                # start 是用来控制递归中从哪里开始选数字的
                # 避免重复、保证子集不重复,且不回头选择已经处理过的元素。
                path.append(nums[i])
                backtrack(i + 1, path)
                path.pop()
        
        backtrack(0, [])
        return res

⏱️复杂度分析 

项目复杂度说明
时间复杂度O(n × 2ⁿ)每个元素有选/不选两种状态,共 2ⁿ 个子集,每个子集最多 n 个元素
空间复杂度O(n)递归栈最大深度为 n

🧱常见易错点 

错误点正确做法说明
没有复制 path要用 path[:] 添加子集副本
忘记 start 控制递归范围start 确保不重复选择已处理过的元素
误把子集当作排列处理子集不需要考虑顺序,只控制是否选入即可

🔁扩展解法(非递归二进制法) 

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        res = []
        n = len(nums)
        for mask in range(1 << n):
            subset = []
            for i in range(n):
                if mask & (1 << i):
                    subset.append(nums[i])
            res.append(subset)
        return res

这种解法将每个子集映射为一个 n 位二进制数,1 表示选,0 表示不选。 

🎯总结

  • 本题是回溯入门题,属于组合型问题。

  • 建议掌握两种方法:

    • ✅ 回溯(递归)

    • ✅ 位运算(非递归)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值