leetcode hot100 78. 子集 递归回溯 medium 位运算法

题目 决策 递归结构
全排列 每层必须选一个 深度固定
子集 每个元素选/不选 深度递增

每个元素都有两种选择:选 或 不选。

python 复制代码
[]
├── [1]
│   ├── [1,2]
│   │   └── [1,2,3]
│   └── [1,3]
├── [2]
│   └── [2,3]
└── [3]

切片回溯

  • 排列:顺序重要 → 所有剩余都可选
  • 组合 / 子集:顺序不重要 → 只能往后选
问题类型 下一层还能选谁 代码
排列 除自己以外所有 nums:i + numsi+1:
子集 / 组合 只选后面的 numsi+1:
python 复制代码
class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        res = []

        def backtrack(nums, tmp):  #(待选列表,已有排列)
            res.append(tmp)   # 当前路径就是一个子集

            # 依次选择待选列表的元素,进入排列。
            for i in range(len(nums)):
                backtrack(nums[i+1:], tmp + [nums[i]])  # 子集顺序不重要,只能往后选

        backtrack(nums, [])
        return res

只能向后选:

python 复制代码
[]
├── [1]
│   ├── [1,2]
│   │   └── [1,2,3]
│   └── [1,3]
├── [2]
│   └── [2,3]
└── [3]

如果数组长度为 n,子集总数 = 2ⁿ

理论最优:O(n × 2ⁿ)

简单写法(位运算法)

每个元素可以选或不选,可以用二进制表示:

python 复制代码
class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        res = [] 
        n = len(nums)

        # 数组长度为 n,子集总数 = 2ⁿ,则一共有2ⁿ种mask模板,2ⁿ=(1 << n)  (左移)
        for mask in range(1 << n):
            subset = []  # 这个mask产生的子集
            # 对每种mask,数组的n位
            for i in range(n):    # 对nums[0], nums[1], nums[2]...
                if mask & (1 << i):  # 判断该位是否为 1
                    subset.append(nums[i])  # 数字加入子集

            res.append(subset)  # 子集加入答案

        return res

时间复杂度

外层循环:2ⁿ

内层循环:n

方法 时间复杂度 额外空间
二进制位图 O(n·2ⁿ) O(n)
回溯 O(n·2ⁿ) O(n)
相关推荐
evans在进步7 小时前
LeetCode 200:岛屿数量——Java DFS 染色法详解
java·leetcode·深度优先
旖旎夜光7 小时前
LeetCode 202:快乐数(双指针问题) —— 题解
数据结构·c++·算法·leetcode·双指针
君君思密达8 小时前
Leetcode Hot 100 题目详解-哈希表
数据结构·算法·leetcode
203号居民10 小时前
LeetCode hot 100 —560. 和为 K 的子数组
java·算法·leetcode
退休倒计时10 小时前
【每日一题】LeetCode 20. 有效的括号 TypeScript
算法·leetcode·职场和发展·typescript
Forever Nore10 小时前
LeetCode 5 最长回文子串 - 中心扩散
linux·算法·leetcode
Forever Nore12 小时前
LeetCode 6 Z 字形变换 - 按行模拟
算法·leetcode
wabs66613 小时前
关于哈希表【力扣383.赎金信的思考】
算法·leetcode·散列表
.道阻且长.1 天前
2.LeetCode算法习题讲解--双指针--复写零
算法·leetcode·职场和发展
To_OC1 天前
LC 438 找到所有字母异位词:暴力超时后,我靠滑动窗口一招搞定
javascript·算法·leetcode