第7章|回溯与搜索

Unit 01 · LeetCode #78

← Unit 00
78
SubsetsBacktracking · start · Power Set

子集没有固定终点:
每个搜索节点本身就是答案。

path 表示当前子集,start 限制下一层只能向更大的索引扩展。进入调用先保存快照,再执行选择、递归与撤销。

题目要求

给定一个元素互不相同的整数数组 nums,返回所有可能的子集。答案不能包含重复子集,顺序任意。

class Solution: def subsets(self, nums: List[int]) -> List[List[int]]: pass
  • 空集和原集合自身都属于答案;
  • 若输入长度为 n,答案数量为 2ⁿ;
  • 元素互不相同,因此无需处理同层值去重。

示例与主模型

nums = [1,2,3] 输出可为: [[],[1],[1,2],[1,2,3],[1,3],[2],[2,3],[3]]

start + for 模型中,每个节点表示一个已选子集。候选窗口为 [start,n),选择 index 后进入 index+1。

记录时机进入每个调用立即执行 result.append(path.copy())。
唯一顺序索引严格递增,同一组元素只生成一次。
完整覆盖每个节点记录,所有合法扩展继续向下。
状态恢复append → recurse → pop 后兄弟分支看到同一父状态。
检测到已保存进度
完整演示看懂状态如何变化
功能提示槽位只保留作用/语义
关键代码补全用代码恢复算法骨架
独立完成迁移到新题
nums = [1,2,3] 的状态空间树
绿色下沿:当前节点本身可记录橙色:当前状态黄色:当前可选状态
当前递归契约
当前 path[]
当前 start0
可用候选1, 2, 3
当前动作记录快照
共享路径 path
候选窗口 [start,n)
result 中的快照
已访问节点1 / 8
已记录子集1 / 8
当前深度0
候选窗口[0,3)
状态是否干净是
关键槽位补全先选槽位 → 再选代码
待填槽位|只提示作用/语义
待选代码标签|顺序随机
每次必须先点击左侧一个槽位,再点击右侧代码标签。选中后会立即拼进右侧代码骨架;再次选择同一槽位可以替换。
from typing import List class Solution: def subsets(self, nums: List[int]) -> List[List[int]]: result = [] path = [] def backtrack(start: int) -> None: result.append(path.copy()) for index in range(start, len(nums)): path.append(nums[index]) backtrack(index + 1) path.pop() backtrack(0) return result
实时拼接后的代码骨架0 / 6
当前认知焦点随运行步骤变化
current
visited
path
start
代码 × 状态逐行联动代码 / path / start / result / 搜索树同步
状态依赖问题
本环节已完成

页面会保留当前状态,观察完成后再手动进入下一环节。

全屏代码编辑