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

【常用算法:查找篇】11.DFS与BFS核心原理及实战全解析

在这里插入图片描述

一、深度优先搜索(DFS):递归回溯的暴力美学

1. 核心思想与搜索状态树

  • 核心逻辑:通过递归深入探索状态树,遇终点或死胡同则回溯,穷举所有可能路径。
  • 状态树模型:以全排列为例,树的层级对应元素选择顺序,叶子节点为完整解。
            根节点(无元素)/   |   \1    2    3 (第1层选第1个元素)/ \  / \  / \2 3 1 3 1 2 (第2层选第2个元素)/   \/   \/   \3     2     2     1 (叶子节点:完整排列)
    

2. 经典问题与代码实现

全排列问题(无重复元素)
def permute(nums):n, result = len(nums), []used = [False] * ndef dfs(path):if len(path) == n:result.append(path.copy())returnfor i in range(n):if not used[i]:used[i] = Truepath.append(nums[i])dfs(path)path.pop()used[i] = Falsedfs([])return result
# 输出:[[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]]
组合问题(C(n, m))
def combine(n, m):result, path = [], []def dfs(start, depth):if depth == m:result.append(path.copy())returnfor i in range(start, n+1):path.append(i)dfs(i+1, depth+1)  # 剪枝:后续元素递增path.pop()dfs(1, 0)return result
# 示例:combine(4, 2) → [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
八皇后问题(位运算优化)
def solve_n_queens(n):col = [False] * nleft_diag = [False] * (2*n-1)  # y-x + n-1right_diag = [False] * (2*n-1)  # y+xresult = []def dfs(y, path):if y == n:result.append(path)returnfor x in range(n):if not col[x] and not left_diag[y-x+n-1] and not right_diag[y+x]:col[x] = left_diag[y-x+n-1] = right_diag[y+x] = Truedfs(y+1, path + [x])col[x] = left_diag[y-x+n-1] = right_diag[y+x] = Falsedfs(0, [])return result
# 输出:8皇后问题的92种解(以列坐标表示)

3. 剪枝策略

  • 约束剪枝:如组合问题中强制递增选择,避免重复组合。
  • 位运算压缩状态:八皇后问题用布尔数组标记列和对角线,O(1)时间判断合法性。
  • 记忆化搜索:记录已访问状态,避免重复计算(如DFS判图环)。

二、广度优先搜索(BFS):分层扩展的最短路径神器

1. 核心思想与数据结构

  • 核心逻辑:用队列实现逐层扩展,首次到达终点即最短路径(适用于无权图)。
  • 关键组件
    • 队列(Queue):存储待探索节点,先进先出。
    • 访问标记(visited):避免重复访问,O(1)查询。
    • 父节点表(parent):路径还原,从终点回溯到起点。

2. 迷宫最短路径问题

Python代码实现
from collections import deque
def bfs_maze(maze, start, end):rows, cols = len(maze), len(maze[0])visited = [[False]*cols for _ in range(rows)]parent = {}queue = deque([start])visited[start[0]][start[1]] = Truedirections = [(-1,0),(1,0),(0,-1),(0,1)]while queue:x, y = queue.popleft()if (x, y) == end:# 路径还原path = []while (x, y) in parent:path.append((x, y))x, y = parent[(x, y)]return [start] + path[::-1]for dx, dy in directions:nx, ny = x+dx, y+dyif 0<=nx<rows and 0<=ny<cols and not visited[nx][ny] and maze[nx][ny]==0:visited[nx][ny] = Trueparent[(nx, ny)] = (x, y)queue.append((nx, ny))return None  # 无解
优化:双向BFS
  • 原理:从起点和终点同时搜索,相遇时终止,减少搜索层数。
  • 适用场景:大规模迷宫(如105×105网格)。

3. 扩展:Dijkstra算法(带权图最短路径)

  • 核心差异:用优先队列(堆)替代普通队列,每次选择当前最短距离节点扩展。
  • 松弛操作:更新相邻节点距离,确保全局最优。
import heapq
def dijkstra(graph, start):dist = {node: float('inf') for node in graph}dist[start] = 0heap = [(0, start)]while heap:current_dist, u = heapq.heappop(heap)if current_dist > dist[u]:continuefor v, w in graph[u]:if dist[v] > dist[u] + w:dist[v] = dist[u] + wheapq.heappush(heap, (dist[v], v))return dist

三、DFS进阶:数独求解的剪枝艺术

1. 问题建模与约束

  • 规则:行、列、宫(3×3)内数字1-9不重复。
  • 状态表示:二维数组board[9][9],0表示空白格。

2. 优化DFS实现

基础递归+回溯
def solve_sudoku(board):blanks = [(i,j) for i in range(9) for j in range(9) if board[i][j]==0]def is_valid(x, y, num):# 行、列、宫检查return not (num in board[x] or any(board[i][y]==num for i in range(9)) orany(board[i][j]==num for i in range((x//3)*3, (x//3+1)*3) for j in range((y//3)*3, (y//3+1)*3)))def dfs(index):if index == len(blanks):return Truex, y = blanks[index]for num in range(1, 10):if is_valid(x, y, num):board[x][y] = numif dfs(index+1):return Trueboard[x][y] = 0return Falsedfs(0)return board
位运算优化(O(1)合法性检查)
row_mask = [0]*9  # 行已用数字位掩码(每位代表1-9)
col_mask = [0]*9
box_mask = [0]*9  # 宫索引0-8for i in range(9):for j in range(9):num = board[i][j]if num != 0:bit = 1 << (num-1)row_mask[i] |= bitcol_mask[j] |= bitbox = (i//3)*3 + (j//3)box_mask[box] |= bitdef is_valid(x, y, num):bit = 1 << (num-1)box = (x//3)*3 + (y//3)return not (row_mask[x] & bit or col_mask[y] & bit or box_mask[box] & bit)

3. 启发式剪枝(MRV策略)

  • 最少剩余值(MRV):优先填充可填数字最少的空白格,减少分支数。
blanks.sort(key=lambda pos: sum(1 for num in 1..9 if is_valid(*pos, num)))

四、总结:DFS vs BFS

特性DFSBFS
核心数据结构递归栈/显式栈队列
路径性质不一定最短(需遍历所有路径)首次到达即最短路径(无权图)
适用场景排列组合、约束满足问题(如数独)迷宫最短路径、层序遍历、社交网络
时间复杂度O(分支数^深度)(依赖剪枝)O(节点数)
空间复杂度O(深度)(递归栈)O(节点数)

🔥 终极算法武器库,助你突破编程思维瓶颈!
从排列组合到复杂约束问题,从无权图到带权图,掌握DFS与BFS核心逻辑,轻松驾驭算法面试与工程实践!🚀

相关文章:

  • Libero离线IP安装
  • 卷java、基础2
  • 前端的面试笔记——HTMLJavaScript篇(二)前端页面性能检测
  • 数据要素及征信公司数据要素实践
  • 【java第15集】java常量和变量区别详解
  • 小乌龟git中的推送账户、作者账户信息修改
  • 谷歌前CEO TED演讲解析:AI 红利的三年窗口期与行业重构
  • 前端的面试笔记——HTMLJavaScript篇(一)
  • C语言——深入理解指针(一)
  • day30 python 模块、包与库的高效使用指南
  • 09、底层注解-@Import导入组件
  • Fastadmin表单分组显示
  • 【2025最新】Spring Boot + Spring AI 玩转智能应用开发
  • 1.1 Epson机器人常用指令1-Print函数、RobotInfo$
  • 实景VR展厅制作流程与众趣科技实景VR展厅应用
  • 将 Element UI 表格拖动功能提取为公共方法
  • Linux云计算训练营笔记day11(Linux CentOS7)
  • 智慧赋能光伏运维——无人机巡检+地面监控双链路覆盖,打造光伏电站管理新标杆
  • Ansible模块——主机名设置和用户/用户组管理
  • 牛客网NC209794:使徒袭来
  • 北京网站建设的价格/专业拓客团队怎么收费
  • 新乡建设公司网站/网站制作企业
  • 区政府网站自查整改和制度建设/搜索引擎优化实训
  • 优秀企业网站的特点/百度一下官网首页下载
  • 阿里云网站如何做淘宝客/如何推广网站方法
  • 福建seo网站/朝阳网站建设