
回溯法Backtracking详解回溯法是一种系统地搜索问题解的通用算法通过深度优先搜索策略在解空间中尝试所有可能的候选解。当发现当前选择无法通向有效解时就回溯到上一步撤销该选择并尝试其他选项。一、核心思想回溯法本质上是暴力搜索 剪枝优化其核心过程可以概括为路径已经做出的选择选择列表当前可以做的选择结束条件到达决策树底部或找到有效解关键特性采用递归实现递归深度等于决策层数通过撤销选择状态重置实现回溯可以剪枝提前终止无效分支的搜索二、经典问题N皇后问题问题描述在n × n的棋盘上放置n个皇后使它们互不攻击任意两个皇后不能在同一行、同一列或同一对角线上。求所有合法放置方案。三、最优子结构与回溯法的区别特性最优子结构动态规划回溯法目标求最优值最大/最小求所有可行解或一个可行解依赖子问题最优解递推无依赖独立尝试所有路径存储通常用表格存储中间结果通常用递归栈或路径数组效率多项式时间复杂度指数级时间复杂度典型应用背包、最短路径八皇后、数独、排列组合四、N皇后回溯法代码实现Pythonpythondef solveNQueens(n): 求解N皇后问题返回所有合法棋盘布局 # 棋盘Q表示皇后.表示空位 board [[. for _ in range(n)] for _ in range(n)] result [] # 存储所有解 # 辅助数组用于O(1)时间判断冲突 cols [False] * n # 列是否被占用 diag1 [False] * (2*n - 1) # 主对角线r - c n - 1 diag2 [False] * (2*n - 1) # 副对角线r c def backtrack(row): 回溯函数在第row行放置皇后 # 结束条件所有行都放置完成 if row n: # 将棋盘转换为字符串列表并加入结果 result.append([.join(row) for row in board]) return # 遍历选择列表当前行的所有列 for col in range(n): # 剪枝检查当前位置是否合法 if cols[col] or diag1[row - col n - 1] or diag2[row col]: continue # 冲突跳过此列 # 做选择放置皇后 board[row][col] Q cols[col] True diag1[row - col n - 1] True diag2[row col] True # 递归进入下一行 backtrack(row 1) # 撤销选择回溯移除皇后恢复状态 board[row][col] . cols[col] False diag1[row - col n - 1] False diag2[row col] False # 从第0行开始搜索 backtrack(0) return result五、回溯法代码结构详解1. 核心框架伪代码textdef backtrack(路径, 选择列表): if 满足结束条件: 记录结果 return for 选择 in 选择列表: # 剪枝可选 if 选择不合法: continue # 1. 做选择 将选择加入路径 # 2. 递归进入下一层 backtrack(新路径, 新的选择列表) # 3. 撤销选择回溯 将选择从路径中移除2. 关键要素说明要素说明示例N皇后路径已做出的选择集合前row行已放置的皇后位置选择列表当前层可用的选项当前行的n个列结束条件到达决策树底部row n所有行都放完剪枝条件提前排除无效选择列或对角线冲突撤销操作恢复状态用于回溯移除皇后重置标志六、另一个经典示例全排列问题问题给定不含重复数字的数组返回所有可能的排列。pythondef permute(nums): 生成数组的所有全排列 result [] path [] # 当前排列路径 used [False] * len(nums) # 标记元素是否已使用 def backtrack(): # 结束条件路径长度等于数组长度 if len(path) len(nums): result.append(path[:]) # 拷贝当前路径 return # 遍历所有元素作为选择 for i in range(len(nums)): # 剪枝跳过已使用的元素 if used[i]: continue # 做选择 path.append(nums[i]) used[i] True # 递归 backtrack() # 撤销选择 path.pop() used[i] False backtrack() return result七、回溯法的时间与空间复杂度时间复杂度最坏情况O(选择数^深度)通常是指数级N皇后O(n!)因为每行可选择的列数递减全排列O(n × n!)n!个排列每个需要复制路径空间复杂度递归栈O(深度)最大等于决策树高度路径存储O(深度) 用于存储当前路径结果存储O(解的数量 × 每个解的大小)八、回溯法 vs 其他算法对比算法适用场景时间复杂度空间复杂度典型问题回溯法组合优化、约束满足指数级O(深度)N皇后、数独动态规划最优子结构、重叠子问题多项式O(状态数)背包、最短路径贪心算法局部最优即全局最优线性/多项式O(1)活动选择、霍夫曼编码分支限界带约束的优化问题指数级但有界O(搜索树大小)旅行商问题九、回溯法的优化技巧1. 剪枝Pruningpython# 示例数独中的剪枝 def is_valid(board, row, col, num): # 检查行、列、3x3宫格 for i in range(9): if board[row][i] num: return False if board[i][col] num: return False if board[3*(row//3) i//3][3*(col//3) i%3] num: return False return True2. 排序优化python# 对选择列表排序优先尝试约束性强的选择 nums.sort() # 或按某种启发式排序3. 记忆化Memoizationpython# 对于重复子问题可以结合记忆化 memo set() def backtrack(state): if state in memo: return memo.add(state) # ... 继续搜索十、总结回溯法的核心公式text回溯 递归 深度优先搜索 状态重置使用场景识别需要所有解或一个解时问题可以分解为多步决策每一步有有限的选择有约束条件需要满足代码实现模板定义递归函数参数包含当前状态编写结束条件遍历所有选择剪枝排除非法选择做选择→递归→撤销选择