📅  最后修改于: 2023-12-03 15:13:39.158000             🧑  作者: Mango
BFS(广度优先搜索)是一种常见的图算法,用于在图中搜索特定的节点或遍历整个图。其思路是从起点开始将所有邻居节点加入到队列中,并依次遍历队首元素的邻居节点,直到找到目标节点或遍历完整个图。
广度优先搜索常见的应用包括:
在 Leetcode 上,很多题目涉及到了 BFS 算法,如:
在使用 BFS 算法之前,需要首先了解图的表达方式。主要有两种方式:邻接矩阵和邻接表。
邻接矩阵是指用二维矩阵来表示图的一种方式。其中,每个数组元素表示一个节点之间的边,值为1表示存在边,值为0表示没有边。
举个例子,对于如下的无向图,其邻接矩阵如下所示:
1 2 3 4 5
--------------
1 | 0 1 1 0 0
2 | 1 0 1 1 0
3 | 1 1 0 0 1
4 | 0 1 0 0 1
5 | 0 0 1 1 0
邻接表是指用链表来表示图的一种方式。其中,每个节点连一条链表来表示它的邻居节点。
同样以上图为例,其邻接表如下所示:
1 -> 2 -> 3
2 -> 1 -> 3 -> 4
3 -> 1 -> 2 -> 5
4 -> 2 -> 5
5 -> 3 -> 4
给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换规则如下:
这是一道经典的 BFS 题目。具体思路如下:
代码片段如下:
from collections import deque
def ladderLength(beginWord: str, endWord: str, wordList: List[str]) -> int:
wordList = set(wordList)
if endWord not in wordList:
return 0
queue = deque([(beginWord, 1)])
while queue:
word, step = queue.popleft()
if word == endWord:
return step
for i in range(len(word)):
for c in "abcdefghijklmnopqrstuvwxyz":
next_word = word[:i] + c + word[i+1:]
if next_word in wordList:
wordList.remove(next_word)
queue.append((next_word, step+1))
return 0
给定一个由 0 和 1 组成的矩阵,求解每个元素到最近的 0 的距离。
这是一道比较典型的 BFS 题目,需要用到多次 BFS 遍历。具体思路如下:
代码片段如下:
from collections import deque
def updateMatrix(matrix):
queue = deque()
row, col = len(matrix), len(matrix[0])
# 将所有为0的节点加入到队列中,并将其的值置0
for i in range(row):
for j in range(col):
if matrix[i][j] == 0:
queue.append((i, j))
else:
matrix[i][j] = float('inf')
# BFS遍历
directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]
while queue:
x, y = queue.popleft()
for dx, dy in directions:
new_x, new_y = x + dx, y + dy
if 0 <= new_x < row and 0 <= new_y < col:
# 如果该节点的新值小于原值,则将其加入到队列中,并更新其值
if matrix[new_x][new_y] > matrix[x][y] + 1:
matrix[new_x][new_y] = matrix[x][y] + 1
queue.append((new_x, new_y))
return matrix
给定一个包含 n 个节点的有向图,判断这个图是否可以完成所有课程的学习。其中,图的节点表示课程,每个结点包含一个课程编号。有些课程之间存在先决条件,例如:想要学习课程0,需要先完成课程1,才能学习课程0。
这是一道比较典型的拓扑排序题目,可以使用 BFS 进行求解。具体思路如下:
代码片段如下:
from collections import deque
from typing import List
def canFinish(numCourses: int, prerequisites: List[List[int]]) -> bool:
# 计算每个节点的入度,并将所有入度为0的节点加入到队列中
in_degrees = [0] * numCourses
graph = [[] for _ in range(numCourses)]
for course, pre in prerequisites:
in_degrees[course] += 1
graph[pre].append(course)
queue = deque([i for i in range(numCourses) if in_degrees[i] == 0])
while queue:
node = queue.popleft()
for nei in graph[node]:
in_degrees[nei] -= 1
if in_degrees[nei] == 0:
queue.append(nei)
return sum(in_degrees) == 0
给定一个二维的矩阵,包含 'X' 和 'O'(字母 O)。
将所有的 'O' 转换为 'X',但是不可把 'X' 转换为 'O'。
感谢 @jianchao-li 添加此题并创建所有测试用例。
这是一道比较典型的 BFS 题目。具体思路如下:
代码片段如下:
from collections import deque
def solve(board: List[List[str]]) -> None:
if not board:
return
# 从四周开始进行 BFS 遍历,标记所有遍历到的 O
m, n = len(board), len(board[0])
queue = deque()
for i in range(m):
for j in range(n):
if board[i][j] == 'O' and (i in {0, m-1} or j in {0, n-1}):
queue.append((i, j))
board[i][j] = 'B'
while queue:
i, j = queue.popleft()
for dx, dy in [(1, 0), (0, 1), (-1, 0), (0, -1)]:
x, y = i + dx, j + dy
if 0 <= x < m and 0 <= y < n and board[x][y] == 'O':
board[x][y] = 'B'
queue.append((x, y))
# 扫描整个矩阵,将所有未被标记为 B 的 O 替换为 X,将所有标记为 B 的 B 替换为 O
for i in range(m):
for j in range(n):
if board[i][j] == 'B':
board[i][j] = 'O'
else:
board[i][j] = 'X'