回溯题解——子集【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)

相关推荐
cellurw1 小时前
俄罗斯方块终端游戏实现 —— C语言系统编程与终端控制
c语言·算法
躲在云朵里`1 小时前
Redis深度解析:核心数据结构、线程模型与高频面试题
数据结构·数据库·redis
林夕忆梦_猫1 小时前
初识C++
开发语言·c++
lightqjx1 小时前
【C++】string类 模拟实现
java·开发语言·c++
Genevieve_xiao1 小时前
【dl】python基础 深度学习中需要用到的python基础
python·深度学习
m0_578267861 小时前
从零开始的python学习(九)P142+P143+P144+P145+P146
笔记·python·学习
只_只2 小时前
B1013 PAT乙级JAVA题解 数素数
java·开发语言
minji...2 小时前
C++ list的模拟实现
开发语言·c++·list
is08152 小时前
You Only Look Once
python
zqy02272 小时前
HTTP的Web服务测试在Python中的实现
python·网络协议·http