当前位置: 首页 > news >正文

最优子结构里藏着的秘密,远比我想象的要多

回溯法(Backtracking)详解

回溯法是一种系统地搜索问题解的通用算法,通过深度优先搜索策略,在解空间中尝试所有可能的候选解。当发现当前选择无法通向有效解时,就回溯到上一步,撤销该选择并尝试其他选项。

一、核心思想

回溯法本质上是暴力搜索 + 剪枝优化,其核心过程可以概括为:

  1. 路径:已经做出的选择

  2. 选择列表:当前可以做的选择

  3. 结束条件:到达决策树底部,或找到有效解

关键特性

  • 采用递归实现,递归深度等于决策层数

  • 通过撤销选择(状态重置)实现回溯

  • 可以剪枝提前终止无效分支的搜索

二、经典问题:N皇后问题

问题描述:在n × n的棋盘上放置n个皇后,使它们互不攻击(任意两个皇后不能在同一行、同一列或同一对角线上)。求所有合法放置方案。

三、最优子结构与回溯法的区别

特性最优子结构(动态规划)回溯法
目标求最优值(最大/最小)求所有可行解或一个可行解
依赖子问题最优解递推无依赖,独立尝试所有路径
存储通常用表格存储中间结果通常用递归栈或路径数组
效率多项式时间复杂度指数级时间复杂度
典型应用背包、最短路径八皇后、数独、排列组合

四、N皇后回溯法代码实现(Python)

python

def 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. 核心框架(伪代码)

text

def backtrack(路径, 选择列表): if 满足结束条件: 记录结果 return for 选择 in 选择列表: # 剪枝(可选) if 选择不合法: continue # 1. 做选择 将选择加入路径 # 2. 递归进入下一层 backtrack(新路径, 新的选择列表) # 3. 撤销选择(回溯) 将选择从路径中移除

2. 关键要素说明

要素说明示例(N皇后)
路径已做出的选择集合前row行已放置的皇后位置
选择列表当前层可用的选项当前行的n个列
结束条件到达决策树底部row == n(所有行都放完)
剪枝条件提前排除无效选择列或对角线冲突
撤销操作恢复状态,用于回溯移除皇后,重置标志

六、另一个经典示例:全排列问题

问题:给定不含重复数字的数组,返回所有可能的排列。

python

def 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. 剪枝(Pruning)

python

# 示例:数独中的剪枝 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 True

2. 排序优化

python

# 对选择列表排序,优先尝试约束性强的选择 nums.sort() # 或按某种启发式排序

3. 记忆化(Memoization)

python

# 对于重复子问题,可以结合记忆化 memo = set() def backtrack(state): if state in memo: return memo.add(state) # ... 继续搜索

十、总结

回溯法的核心公式

text

回溯 = 递归 + 深度优先搜索 + 状态重置

使用场景识别

  • 需要所有解一个解

  • 问题可以分解为多步决策

  • 每一步有有限的选择

  • 约束条件需要满足

代码实现模板

  1. 定义递归函数,参数包含当前状态

  2. 编写结束条件

  3. 遍历所有选择

  4. 剪枝排除非法选择

  5. 做选择→递归→撤销选择

http://www.jsqmd.com/news/1397745/

相关文章:

  • Steam创意工坊下载器WorkshopDL实测手记:把创意工坊模组免费搬进非Steam游戏
  • Kimi LeetCode 3910. 统计节点和为偶数的连通子图 Python3实现
  • 宇视出入口设备默认IP地址全解析与网络寻址实战指南
  • 【创新方案】绝区零一条龙全自动辅助工具:解放双手的智能托管引擎
  • 显卡驱动卸载不干净?Display Driver Uninstaller 保姆级清理指南,一次解决残留难题
  • Cat.1 DTU与Cat.4 DTU怎么选?带宽够用吗?
  • 告别月费订阅:Sunshine 自托管游戏串流,把家里的电脑变成随身的私人游戏库
  • 深圳处置闲置黄金实地探店,理清报价差别学会理性选择回收渠道 - 日常前沿快讯
  • 从One-Hot到BERT:深入解析Embedding技术原理、演进与工程实践
  • 3步完成网易云NCM转MP3:ncmdump开源解密工具上手指南
  • 还在手动处理微信小店订单?这款铺货工具支持批量下单,多店铺管理省心省事 - 抖大侠
  • 网盘直链下载助手是什么?三步绕开官方客户端拿到百度网盘等8大网盘真实下载地址
  • tModLoader常见问题排查终极手册:一次把“装不上、进不去、玩不爽“彻底问清楚
  • 网盘下载慢到怀疑人生?三步装上这款网盘直链解析工具,让文件“嗖“地飞进电脑
  • 实习生视角:一套轻量化 IT 设备管理系统,如何把机房运维的“糊涂账“算清楚
  • 免费开源文档下载工具:kill-doc 让 30+ 平台文档一键下载
  • 44. 【Java】线程安全与同步:synchronized与Lock
  • 市面上做学工一体化平台的厂家不少,到底该怎么挑
  • 基于MiniCPM5-1B构建本地研究智能体:低成本实现工具调用与数据隐私
  • VMProtect逆向分析:从虚拟机原理到实战还原技术
  • 从收藏夹空转到本地整库:抖音视频批量下载的开源方案实测记录
  • 2026绵阳防水补漏全解析|雨季、回南天房屋渗漏实用指南 - 筑宅安
  • 2026年宁波能做智慧燃气安全监测管理系统的公司有哪些?
  • 猿人学 第一题 js混淆-源码乱码
  • 国产大模型与AI Agent比价工具:如何量化集成成本与动态计算TCO
  • Meta Muse Glimmer-30B部署实战:从Hugging Face到vLLM的高效推理指南
  • Python函数的定义调用参数和返回值
  • 【刚刚获悉】深圳全屋定制看哪些**认证? - 各行各业Ethan说
  • NCM文件解密3步走:免费开源的ncmdump,让下载的歌真正属于你
  • 互加科技拆解微盟星启GEO五阶优化第四环:监测,GEO闭环不可或缺的技术环节 - 天下观知