回溯题解——子集【LeetCode】二进制枚举法

78. 子集

✅ 一、算法逻辑讲解(逐步通顺解释)

这段代码的目标是:给定一个不含重复元素的整数数组 nums,返回其所有可能的子集(幂集)

步骤解析:

  1. 1 << len(nums)

    • 这是 2^n 的简写方式,表示子集的总数。

    • 因为一个长度为 n 的集合一共有 2^n 个子集。

  2. for i in range(1<<len(nums)):

    • i02^n - 1

    • 每个数字 i 的二进制表示就是一个子集的"选取方案",每一位表示该位置元素选不选。

      • 例如:nums = [a, b, c]i = 5 = 0b101 表示选 ac(第0和第2位是1)。
  3. [x for j, x in enumerate(nums) if i >> j & 1]

    • 枚举 nums 中的每个元素 x 及其下标 j

    • 如果 i 的第 j 位是 1,就说明这个元素被选入子集。

    • i >> j & 1 是判断第 j 位是否为1的经典写法。

  4. 将生成的子集 subsets 加入答案列表 ans 中。

  5. 返回所有子集的列表。


⭐ 二、核心思路

核心点是:用位运算枚举所有子集。

  • 将每一个子集的选取用一个 n 位二进制数表示(0 表示不选,1 表示选)。

  • 枚举 02^n - 1,每个整数的二进制形式唯一表示一个子集。

  • 位运算用于高效判断哪些元素被选中。

这是一种非常高效、简洁的生成子集的方式,尤其适用于集合元素较少(如 n ≤ 20)的场景。

python 复制代码
class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        ans = []
        for i in range(1<<len(nums)):
            subsets = [x for j,x in enumerate(nums) if i>>j&1]
            ans.append(subsets)
        return ans

⏱ 三、时间复杂度分析

时间复杂度:O(n * 2^n)

  • 一共有 2^n 个子集。

  • 每个子集最多需要扫描 n 个元素来判断是否包含(通过 i >> j & 1 判断)。

  • 所以总的复杂度是:O(n * 2^n)

比如 nums = [1,2,3],就需要计算 2^3 = 8 个子集,每个最多判断 3 个位置。


💾 四、空间复杂度分析

空间复杂度:O(n * 2^n)(输出结果空间)

  • 每个子集可能长度为 n,最多有 2^n 个子集。

  • 所以总的空间用于保存输出结果是 O(n * 2^n)

额外空间(不含输出):O(n)

  • 每次生成一个子集使用一个列表(临时变量 subsets),最多长度为 n

  • 所以辅助空间是 O(n)

相关推荐
PacosonSWJTU21 小时前
mac-python解释器理解与python安装
开发语言·python
Trouvaille ~21 小时前
【Linux】线程同步与互斥(一):线程互斥原理与mutex详解
linux·运维·服务器·c++·算法·线程·互斥锁
Remember_99321 小时前
Java 单例模式深度解析:设计原理、实现范式与企业级应用场景
java·开发语言·javascript·单例模式·ecmascript
urkay-21 小时前
Android 中实现 HMAC-SHA256
android·开发语言·python
代码or搬砖21 小时前
ReentranLock中AQS讲解
java·开发语言·redis
DN202021 小时前
AI销售机器人的隐私痛点与破解之道
人工智能·python·机器学习·机器人·节日
rainbow688921 小时前
C++智能指针实战:从入门到精通
java·开发语言
2501_9403152621 小时前
leetcode统计一致字符串的数目(哈希表)
算法·哈希算法·散列表
瑞雪兆丰年兮21 小时前
[从0开始学Java|第五天]Java循环高级综合练习
java·开发语言
清铎21 小时前
项目_Agent实战
开发语言·人工智能·深度学习·算法·机器学习