第7章|回溯与搜索

Unit 07 · LeetCode #131 · 重构版

← Unit 06
131
Palindrome PartitioningCut End · Validate Segment

选择的不是某个字符,
而是这一段在哪里结束。

进入 backtrack(start) 时,path 已覆盖 s[:start]。本层枚举 end,只有回文片段 s[start:end+1] 才能进入真实递归树;非法片段只发生在候选检查层。

题目模型

将字符串切成若干连续片段,每个片段必须是回文,且所有片段首尾相接完整覆盖输入。

state = start
candidate = s[start:end+1]
next_state = end + 1
  • 答案:["a","a","b"]、["aa","b"];
  • "ab"、"aab" 在递归之前被过滤;
  • 非法候选不应被画成递归节点。

核心契约

"".join(path) == s[:start]
all(piece is palindrome for piece in path)

候选先验证,再 append;真正进入子调用时,current/start/visited/递归栈 才切换到新状态。

Cut-End Choice

一层枚举的是终点 end,而不是孤立字符。

Prefix Coverage

path 拼接必须恰好覆盖 s[:start]。

Feasibility Filter

非回文只被检查和 continue,不进入树。

Complete Consumption

start == len(s) 才记录完整分割。

1. 选择切割终点
2. 回文候选过滤
3. 完整消费与撤销
4. 边界错误实验
5. 渐隐脚手架
6. 迁移 #93
s = "aab"|真实递归状态树

字符串覆盖

当前 path

当前层候选

递归栈

当前状态

真实树节点
已访问
已记录答案
queue—(DFS递归)
覆盖状态
渐隐脚手架完整演示 → 功能提示槽位 → 关键代码补全 → 独立完成
关键槽位补全先选左侧槽位 → 再选右侧代码
实时拼接后的代码骨架只拼接已建立的语义映射
当前认知焦点

此刻不应该提前改变
本行真正负责
代码 × 状态逐行联动
状态依赖问题|执行 path.append(piece) 后,哪些状态还不能提前切换到子节点?

本题用于检查理解,不会阻塞“下一步”或“自动播放”。

#131 独立完成

迁移题:LeetCode #93 复原 IP 地址

搜索骨架仍是“枚举切割终点 → 验证片段 → append → end+1 → pop”。变化在于片段合法性改为 IP 规则,并增加固定 4 段与容量剪枝。

Unit 07 Skill 卡

字符串分割回溯的核心不是“选字符”,而是枚举下一段终点。非法片段只停留在候选层;真正进入递归节点时才推进 start、current、visited 与递归栈。

状态start + path
候选s[start:end+1]
过滤递归前验证片段
下一层end + 1
树节点只保留真实 backtrack 状态
#93迁移四段 + IP规则 + 容量剪枝