回溯是深度优先搜索的一种写法:把候选方案看成一棵决策树,每层做一次选择,发现不可行就撤销,回到上一个分叉。组合关心选哪些,排列还关心顺序,子集则常在每个节点都收集答案。

统一步骤是:判断终止并记录快照;枚举当前层候选;跳过不合法选择;加入路径;递归下一层;撤销路径。伪代码如下:

1
2
3
4
5
6
7
search(state):
if complete(state): save(copy(path))
for choice in candidates(state):
if invalid(choice): continue
apply(choice)
search(nextState)
undo(choice)

去重必须分清层级。同一树层避免选相同值,可在排序后跳过相邻重复候选;同一路径避免重复使用元素,则用 used 数组。剪枝来自约束:剩余元素不足、当前和已超目标、当前方案不会优于最优解时,应提前返回。排序往往让这些判断更早生效。

若每个元素都有选或不选两种可能,搜索规模约 O(2^n);全排列可达 O(n!),保存每个答案还要乘路径复制成本。递归栈通常为 O(n),输出空间另算。回溯并不会消除指数爆炸,只是系统枚举并尽早排除无效分支。

常见误区是忘记撤销、保存了可变路径引用、把“去重”错误地跨层使用,以及在没有单调条件时随意剪枝。小结:先画出决策树,明确每层含义和路径约束,再写选择—递归—撤销,代码自然会稳定。