前言 广度优先搜索(Breadth-First Search,简称BFS)是一种用于遍历或搜索树或图的算法。与深度优先搜索不同,BFS 从源节点开始,首先访问所有邻近节点,然后才移动到下一层节点。
BFS 算法基本原理 BFS 使用队列数据结构来跟踪需要访问的节点:
将起始节点放入队列中 
当队列不为空时:
取出队列头部节点并访问 
将该节点的所有未访问的邻居节点加入队列 
标记这些邻居节点为已访问 
 
 
 
BFS 代码模板 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from  collections import  dequedef  bfs (graph, start ):         queue = deque([start])          visited = {start}          while  queue:                  node = queue.popleft()         print (node)                             for  neighbor in  graph[node]:             if  neighbor not  in  visited:                 visited.add(neighbor)                 queue.append(neighbor) 
BFS 的时间和空间复杂度 
时间复杂度:$O(V + E)$,其中 $V$ 是节点数,$E$ 是边数 
空间复杂度:$O(V)$,最坏情况下,队列中可能包含所有节点 
 
BFS 在 LeetCode 中的应用 1. 二叉树层序遍历 (LeetCode 102) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class  TreeNode :    def  __init__ (self, val=0 , left=None , right=None  ):         self.val = val         self.left = left         self.right = right def  levelOrder (root ):    if  not  root:         return  []          result = []     queue = deque([root])          while  queue:         level_size = len (queue)         current_level = []                  for  _ in  range (level_size):             node = queue.popleft()             current_level.append(node.val)                          if  node.left:                 queue.append(node.left)             if  node.right:                 queue.append(node.right)                  result.append(current_level)          return  result 
2. 岛屿数量 (LeetCode 200) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 def  numIslands (grid ):    if  not  grid:         return  0           rows, cols = len (grid), len (grid[0 ])     count = 0           for  i in  range (rows):         for  j in  range (cols):             if  grid[i][j] == '1' :                 count += 1                                   bfs_island(grid, i, j)          return  count def  bfs_island (grid, i, j ):    rows, cols = len (grid), len (grid[0 ])     queue = deque([(i, j)])     grid[i][j] = '0'             directions = [(0 , 1 ), (1 , 0 ), (0 , -1 ), (-1 , 0 )]          while  queue:         r, c = queue.popleft()                  for  dr, dc in  directions:             nr, nc = r + dr, c + dc             if  (0  <= nr < rows and  0  <= nc < cols and  grid[nr][nc] == '1' ):                 queue.append((nr, nc))                 grid[nr][nc] = '0'    
3. 单词接龙 (LeetCode 127) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 def  ladderLength (beginWord, endWord, wordList ):    word_set = set (wordList)     if  endWord not  in  word_set:         return  0           queue = deque([(beginWord, 1 )])       visited = {beginWord}          while  queue:         current_word, level = queue.popleft()                           for  i in  range (len (current_word)):                          for  c in  'abcdefghijklmnopqrstuvwxyz' :                 next_word = current_word[:i] + c + current_word[i+1 :]                                  if  next_word == endWord:                     return  level + 1                                   if  next_word in  word_set and  next_word not  in  visited:                     visited.add(next_word)                     queue.append((next_word, level + 1 ))          return  0  
4. 腐烂的橘子 (LeetCode 994) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 def  orangesRotting (grid ):    rows, cols = len (grid), len (grid[0 ])     queue = deque()     fresh_count = 0                for  i in  range (rows):         for  j in  range (cols):             if  grid[i][j] == 2 :                 queue.append((i, j, 0 ))               elif  grid[i][j] == 1 :                 fresh_count += 1           if  fresh_count == 0 :         return  0           directions = [(0 , 1 ), (1 , 0 ), (0 , -1 ), (-1 , 0 )]     max_minutes = 0           while  queue:         r, c, minutes = queue.popleft()         max_minutes = max (max_minutes, minutes)                  for  dr, dc in  directions:             nr, nc = r + dr, c + dc             if  (0  <= nr < rows and  0  <= nc < cols and  grid[nr][nc] == 1 ):                 grid[nr][nc] = 2                  fresh_count -= 1                  queue.append((nr, nc, minutes + 1 ))          return  max_minutes if  fresh_count == 0  else  -1  
BFS 的优缺点 优点 
保证找到最短路径(对于无权图) 
适合寻找最少步骤的问题 
对于层次遍历非常有效 
 
缺点 
相比DFS,内存消耗更大 
对于很宽的图,可能会占用大量内存 
不适合搜索目标较深且分支很多的情况 
 
后记 BFS 是一种强大的图遍历算法,特别适合解决最短路径、层次遍历等问题。在 LeetCode 中,BFS 常用于解决图、树的遍历问题,以及迷宫类、变换类的问题。掌握 BFS 可以帮助我们更高效地解决许多复杂问题。