算法精讲:广度优先搜索(BFS)——从原理到实战的完整指南
算法精讲:广度优先搜索(BFS)——从原理到实战的完整指南
1. 算法深度解析
1.1 什么是广度优先搜索?
- 层次性:按距离起始节点的远近顺序访问
- 最优性:在无权图中保证找到最短路径
- 完备性:只要解存在,一定能找到
- 队列驱动:基于FIFO队列实现
1.2 算法思想与数学基础
- 初始化:所有节点颜色为白色(未访问)
- 将s标记为灰色(已发现但未处理),d[s] = 0
- 将s加入队列Q
- while Q ≠ ∅:
- u = Dequeue(Q)
- 对每个v ∈ Adj[u]:
- 如果v为白色:颜色变灰,d[v] = d[u] + 1,Enqueue(Q, v)
- 颜色变黑(已处理)
2. 核心实现与优化
2.1 图的多种表示方法
import java.util.*;
// 方法1:通用图节点类
class GraphNode {
public int val;
public List<GraphNode> neighbors;
public boolean visited;
public GraphNode(int val) {
this.val = val;
this.neighbors = new ArrayList<>();
this.visited = false;
}
public void addNeighbor(GraphNode neighbor) {
this.neighbors.add(neighbor);
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
GraphNode node = (GraphNode) obj;
return val == node.val;
}
@Override
public int hashCode() {
return Objects.hash(val);
}
}
// 方法2:紧凑型图表示(适合稠密图)
class CompactGraph {
private int[][] adjacencyMatrix;
private int size;
public CompactGraph(int n) {
this.size = n;
this.adjacencyMatrix = new int[n][n];
}
public void addEdge(int u, int v) {
adjacencyMatrix[u][v] = 1;
adjacencyMatrix[v][u] = 1; // 无向图
}
public List<Integer> getNeighbors(int node) {
List<Integer> neighbors = new ArrayList<>();
for (int i = 0; i < size; i++) {
if (adjacencyMatrix[node][i] == 1) {
neighbors.add(i);
}
}
return neighbors;
}
}
// 方法3:高效邻接表
class EfficientGraph {
private Map<Integer, Set<Integer>> adjList;
public EfficientGraph() {
this.adjList = new HashMap<>();
}
public void addEdge(int u, int v) {
adjList.computeIfAbsent(u, k -> new HashSet<>()).add(v);
adjList.computeIfAbsent(v, k -> new HashSet<>()).add(u);
}
public Set<Integer> getNeighbors(int node) {
return adjList.getOrDefault(node, new HashSet<>());
}
}
2.2 基础BFS实现(生产级别)
/**
* 标准BFS实现 - 生产环境级别
* 时间复杂度: O(V + E), 空间复杂度: O(V)
*/
public static List<Integer> standardBFS(GraphNode start) {
List<Integer> traversalOrder = new ArrayList<>();
if (start == null) return traversalOrder;
Queue<GraphNode> queue = new LinkedList<>();
Set<GraphNode> visited = new HashSet<>();
// 初始化
queue.offer(start);
visited.add(start);
while (!queue.isEmpty()) {
GraphNode current = queue.poll();
traversalOrder.add(current.val);
// 处理所有未访问的邻居
for (GraphNode neighbor : current.neighbors) {
if (!visited.contains(neighbor)) {
visited.add(neighbor);
queue.offer(neighbor);
}
}
}
return traversalOrder;
}
/**
* 带距离计算的BFS
* 返回每个节点到起点的最短距离
*/
public static Map<GraphNode, Integer> bfsWithDistance(GraphNode start) {
Map<GraphNode, Integer> distances = new HashMap<>();
if (start == null) return distances;
Queue<GraphNode> queue = new LinkedList<>();
Set<GraphNode> visited = new HashSet<>();
queue.offer(start);
visited.add(start);
distances.put(start, 0);
while (!queue.isEmpty()) {
GraphNode current = queue.poll();
int currentDistance = distances.get(current);
for (GraphNode neighbor : current.neighbors) {
if (!visited.contains(neighbor)) {
visited.add(neighbor);
distances.put(neighbor, currentDistance + 1);
queue.offer(neighbor);
}
}
}
return distances;
}
/**
* 带路径重建的BFS
* 可以找到从起点到任意节点的最短路径
*/
public static class BFSResult {
public Map<GraphNode, Integer> distances;
public Map<GraphNode, GraphNode> predecessors;
public BFSResult() {
this.distances = new HashMap<>();
this.predecessors = new HashMap<>();
}
}
public static BFSResult bfsWithPathReconstruction(GraphNode start) {
BFSResult result = new BFSResult();
if (start == null) return result;
Queue<GraphNode> queue = new LinkedList<>();
Set<GraphNode> visited = new HashSet<>();
queue.offer(start);
visited.add(start);
result.distances.put(start, 0);
result.predecessors.put(start, null);
while (!queue.isEmpty()) {
GraphNode current = queue.poll();
int currentDistance = result.distances.get(current);
for (GraphNode neighbor : current.neighbors) {
if (!visited.contains(neighbor)) {
visited.add(neighbor);
result.distances.put(neighbor, currentDistance + 1);
result.predecessors.put(neighbor, current);
queue.offer(neighbor);
}
}
}
return result;
}
/**
* 重建从起点到目标节点的最短路径
*/
public static List<Integer> reconstructPath(GraphNode start, GraphNode target,
Map<GraphNode, GraphNode> predecessors) {
List<Integer> path = new LinkedList<>();
if (!predecessors.containsKey(target)) return path; // 不可达
GraphNode current = target;
while (current != null) {
path.add(0, current.val);
current = predecessors.get(current);
}
// 验证路径是否真的从start开始
if (path.get(0) != start.val) {
return new ArrayList<>(); // 没有有效路径
}
return path;
}
}
2.3 层级遍历的多种变体
* BFS层级遍历的高级实现
*/
public class AdvancedLevelBFS {
/**
* 标准层级遍历
*/
public static List<List<Integer>> levelOrderTraversal(GraphNode start) {
List<List<Integer>> result = new ArrayList<>();
if (start == null) return result;
Queue<GraphNode> queue = new LinkedList<>();
Set<GraphNode> visited = new HashSet<>();
queue.offer(start);
visited.add(start);
while (!queue.isEmpty()) {
int levelSize = queue.size();
List<Integer> currentLevel = new ArrayList<>();
for (int i = 0; i < levelSize; i++) {
GraphNode current = queue.poll();
currentLevel.add(current.val);
for (GraphNode neighbor : current.neighbors) {
if (!visited.contains(neighbor)) {
visited.add(neighbor);
queue.offer(neighbor);
}
}
}
result.add(currentLevel);
}
return result;
}
/**
* 之字形层级遍历
*/
public static List<List<Integer>> zigzagLevelOrder(GraphNode start) {
List<List<Integer>> result = new ArrayList<>();
if (start == null) return result;
Queue<GraphNode> queue = new LinkedList<>();
Set<GraphNode> visited = new HashSet<>();
boolean leftToRight = true;
queue.offer(start);
visited.add(start);
while (!queue.isEmpty()) {
int levelSize = queue.size();
LinkedList<Integer> currentLevel = new LinkedList<>();
for (int i = 0; i < levelSize; i++) {
GraphNode current = queue.poll();
if (leftToRight) {
currentLevel.addLast(current.val);
} else {
currentLevel.addFirst(current.val);
}
for (GraphNode neighbor : current.neighbors) {
if (!visited.contains(neighbor)) {
visited.add(neighbor);
queue.offer(neighbor);
}
}
}
result.add(new ArrayList<>(currentLevel));
leftToRight = !leftToRight;
}
return result;
}
/**
* 获取每层最右侧节点(右视图)
*/
public static List<Integer> rightSideView(GraphNode start) {
List<Integer> result = new ArrayList<>();
if (start == null) return result;
Queue<GraphNode> queue = new LinkedList<>();
Set<GraphNode> visited = new HashSet<>();
queue.offer(start);
visited.add(start);
while (!queue.isEmpty()) {
int levelSize = queue.size();
for (int i = 0; i < levelSize; i++) {
GraphNode current = queue.poll();
// 如果是当前层最后一个节点,加入结果
if (i == levelSize - 1) {
result.add(current.val);
}
for (GraphNode neighbor : current.neighbors) {
if (!visited.contains(neighbor)) {
visited.add(neighbor);
queue.offer(neighbor);
}
}
}
}
return result;
}
}
3. 高级应用与LeetCode实战
3.1 矩阵类问题
* 矩阵BFS问题合集
*/
public class MatrixBFSProblems {
/**
* LeetCode 200 - 岛屿数量
* 时间复杂度: O(M×N), 空间复杂度: O(min(M,N))
*/
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0) return 0;
int rows = grid.length;
int cols = grid[0].length;
int islandCount = 0;
int[][] directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (grid[i][j] == '1') {
islandCount++;
bfsMarkIsland(grid, i, j, rows, cols, directions);
}
}
}
return islandCount;
}
private void bfsMarkIsland(char[][] grid, int row, int col,
int rows, int cols, int[][] directions) {
Queue<int[]> queue = new LinkedList<>();
queue.offer(new int[]{row, col});
grid[row][col] = '0'; // 标记为已访问
while (!queue.isEmpty()) {
int[] current = queue.poll();
int currentRow = current[0];
int currentCol = current[1];
for (int[] dir : directions) {
int newRow = currentRow + dir[0];
int newCol = currentCol + dir[1];
if (newRow >= 0 && newRow < rows &&
newCol >= 0 && newCol < cols &&
grid[newRow][newCol] == '1') {
grid[newRow][newCol] = '0';
queue.offer(new int[]{newRow, newCol});
}
}
}
}
/**
* LeetCode 542 - 01矩阵
* 多源BFS经典问题
*/
public int[][] updateMatrix(int[][] mat) {
if (mat == null || mat.length == 0) return mat;
int rows = mat.length;
int cols = mat[0].length;
int[][] result = new int[rows][cols];
Queue<int[]> queue = new LinkedList<>();
int[][] directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
// 初始化:所有0的位置入队,1的位置标记为最大值
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (mat[i][j] == 0) {
queue.offer(new int[]{i, j});
result[i][j] = 0;
} else {
result[i][j] = Integer.MAX_VALUE;
}
}
}
// 多源BFS
while (!queue.isEmpty()) {
int[] current = queue.poll();
int row = current[0];
int col = current[1];
for (int[] dir : directions) {
int newRow = row + dir[0];
int newCol = col + dir[1];
if (newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols) {
if (result[newRow][newCol] > result[row][col] + 1) {
result[newRow][newCol] = result[row][col] + 1;
queue.offer(new int[]{newRow, newCol});
}
}
}
}
return result;
}
/**
* LeetCode 286 - 墙与门
* 填充每个房间到最近门的距离
*/
public void wallsAndGates(int[][] rooms) {
if (rooms == null || rooms.length == 0) return;
int rows = rooms.length;
int cols = rooms[0].length;
Queue<int[]> queue = new LinkedList<>();
int[][] directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
// 所有门入队
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (rooms[i][j] == 0) {
queue.offer(new int[]{i, j});
}
}
}
// BFS遍历
while (!queue.isEmpty()) {
int[] current = queue.poll();
int row = current[0];
int col = current[1];
for (int[] dir : directions) {
int newRow = row + dir[0];
int newCol = col + dir[1];
if (newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols
&& rooms[newRow][newCol] == Integer.MAX_VALUE) {
rooms[newRow][newCol] = rooms[row][col] + 1;
queue.offer(new int[]{newRow, newCol});
}
}
}
}
}
3.2 字符串与状态搜索
* 字符串BFS问题
*/
public class StringBFSProblems {
/**
* LeetCode 127 - 单词接龙
* 双向BFS优化版本
*/
public int ladderLength(String beginWord, String endWord, List<String> wordList) {
Set<String> wordSet = new HashSet<>(wordList);
if (!wordSet.contains(endWord)) return 0;
Set<String> beginSet = new HashSet<>();
Set<String> endSet = new HashSet<>();
Set<String> visited = new HashSet<>();
beginSet.add(beginWord);
endSet.add(endWord);
visited.add(beginWord);
visited.add(endWord);
int length = 1;
while (!beginSet.isEmpty() && !endSet.isEmpty()) {
// 总是从较小的集合开始扩展
if (beginSet.size() > endSet.size()) {
Set<String> temp = beginSet;
beginSet = endSet;
endSet = temp;
}
Set<String> nextSet = new HashSet<>();
for (String word : beginSet) {
char[] charArray = word.toCharArray();
for (int i = 0; i < charArray.length; i++) {
char originalChar = charArray[i];
for (char c = 'a'; c <= 'z'; c++) {
if (c == originalChar) continue;
charArray[i] = c;
String newWord = new String(charArray);
if (endSet.contains(newWord)) {
return length + 1;
}
if (wordSet.contains(newWord) && !visited.contains(newWord)) {
visited.add(newWord);
nextSet.add(newWord);
}
}
charArray[i] = originalChar;
}
}
beginSet = nextSet;
length++;
}
return 0;
}
/**
* LeetCode 279 - 完全平方数
* BFS求最短路径的变种
*/
public int numSquares(int n) {
if (n <= 0) return 0;
Queue<Integer> queue = new LinkedList<>();
Set<Integer> visited = new HashSet<>();
int[] squares = generateSquares(n);
queue.offer(n);
visited.add(n);
int level = 0;
while (!queue.isEmpty()) {
int size = queue.size();
level++;
for (int i = 0; i < size; i++) {
int current = queue.poll();
for (int square : squares) {
int next = current - square;
if (next < 0) break;
if (next == 0) return level;
if (!visited.contains(next)) {
visited.add(next);
queue.offer(next);
}
}
}
}
return n; // 最坏情况,全部由1组成
}
private int[] generateSquares(int n) {
int maxSquareRoot = (int) Math.sqrt(n);
int[] squares = new int[maxSquareRoot];
for (int i = 0; i < maxSquareRoot; i++) {
squares[i] = (i + 1) * (i + 1);
}
return squares;
}
}
4. 性能优化与高级技巧
4.1 双向BFS深度优化
* 高级双向BFS实现
*/
public class AdvancedBidirectionalBFS {
public static int bidirectionalBFS(GraphNode start, GraphNode end) {
if (start == null || end == null) return -1;
if (start == end) return 0;
// 使用两个队列和两个访问集合
Queue<GraphNode> queueA = new LinkedList<>();
Queue<GraphNode> queueB = new LinkedList<>();
Map<GraphNode, Integer> visitedA = new HashMap<>(); // 记录节点和距离
Map<GraphNode, Integer> visitedB = new HashMap<>();
// 初始化
queueA.offer(start);
queueB.offer(end);
visitedA.put(start, 0);
visitedB.put(end, 0);
while (!queueA.isEmpty() && !queueB.isEmpty()) {
// 从较小队列扩展
int distance = expandQueue(queueA, visitedA, visitedB);
if (distance != -1) return distance;
distance = expandQueue(queueB, visitedB, visitedA);
if (distance != -1) return distance;
}
return -1;
}
private static int expandQueue(Queue<GraphNode> queue,
Map<GraphNode, Integer> visitedFromThisSide,
Map<GraphNode, Integer> visitedFromOtherSide) {
if (queue.isEmpty()) return -1;
GraphNode current = queue.poll();
int currentDistance = visitedFromThisSide.get(current);
for (GraphNode neighbor : current.neighbors) {
if (!visitedFromThisSide.containsKey(neighbor)) {
// 检查是否在另一侧被访问过
if (visitedFromOtherSide.containsKey(neighbor)) {
return currentDistance + 1 + visitedFromOtherSide.get(neighbor);
}
visitedFromThisSide.put(neighbor, currentDistance + 1);
queue.offer(neighbor);
}
}
return -1;
}
}
4.2 启发式BFS(A*算法)
* A*搜索算法 - BFS的启发式扩展
*/
public class AStarSearch {
static class NodeWithPriority implements Comparable<NodeWithPriority> {
GraphNode node;
int cost; // g(n):从起点到当前节点的实际代价
int heuristic; // h(n):到目标的估计代价
int total; // f(n) = g(n) + h(n)
public NodeWithPriority(GraphNode node, int cost, int heuristic) {
this.node = node;
this.cost = cost;
this.heuristic = heuristic;
this.total = cost + heuristic;
}
@Override
public int compareTo(NodeWithPriority other) {
return Integer.compare(this.total, other.total);
}
}
/**
* A*搜索实现
* @param start 起始节点
* @param end 目标节点
* @param heuristic 启发式函数
* @return 最短路径长度,-1表示不可达
*/
public static int aStarSearch(GraphNode start, GraphNode end,
java.util.function.Function<GraphNode, Integer> heuristic) {
PriorityQueue<NodeWithPriority> openSet = new PriorityQueue<>();
Map<GraphNode, Integer> gScore = new HashMap<>(); // 实际代价
Map<GraphNode, GraphNode> cameFrom = new HashMap<>(); // 路径重建
// 初始化
gScore.put(start, 0);
openSet.offer(new NodeWithPriority(start, 0, heuristic.apply(start)));
while (!openSet.isEmpty()) {
NodeWithPriority current = openSet.poll();
if (current.node == end) {
return current.cost; // 找到目标
}
// 如果当前路径不是最优,跳过
if (current.cost > gScore.getOrDefault(current.node, Integer.MAX_VALUE)) {
continue;
}
for (GraphNode neighbor : current.node.neighbors) {
int tentativeGScore = gScore.get(current.node) + 1; // 假设边权为1
if (tentativeGScore < gScore.getOrDefault(neighbor, Integer.MAX_VALUE)) {
// 找到更优路径
cameFrom.put(neighbor, current.node);
gScore.put(neighbor, tentativeGScore);
int fScore = tentativeGScore + heuristic.apply(neighbor);
openSet.offer(new NodeWithPriority(neighbor, tentativeGScore, fScore - tentativeGScore));
}
}
}
return -1; // 不可达
}
}
5. 复杂度分析与工程实践
5.1 详细复杂度分析
- 基础BFS:O(V + E)
- 每个节点入队出队一次:O(V)
- 每条边检查一次:O(E)
- 矩阵BFS:O(M × N)
- 每个单元格访问一次
- 双向BFS:O(b^(d/2)),其中b是分支因子,d是深度
- 比传统BFS的O(b^d)有显著提升
- 最坏情况:O(V) - 所有节点都在队列中
- 最佳情况:O(1) - 线性图
- 平均情况:O(最大层宽度)
5.2 工程实践建议
* 生产环境BFS最佳实践
*/
public class ProductionBFSBestPractices {
/**
* 带容量限制的BFS - 防止内存溢出
*/
public static List<Integer> bfsWithCapacityLimit(GraphNode start, int maxNodes) {
List<Integer> result = new ArrayList<>();
if (start == null) return result;
Queue<GraphNode> queue = new LinkedList<>();
Set<GraphNode> visited = new HashSet<>();
int processedNodes = 0;
queue.offer(start);
visited.add(start);
while (!queue.isEmpty() && processedNodes < maxNodes) {
GraphNode current = queue.poll();
result.add(current.val);
processedNodes++;
for (GraphNode neighbor : current.neighbors) {
if (!visited.contains(neighbor) && processedNodes < maxNodes) {
visited.add(neighbor);
queue.offer(neighbor);
}
}
}
return result;
}
/**
* 带超时控制的BFS
*/
public static List<Integer> bfsWithTimeout(GraphNode start, long timeoutMillis) {
List<Integer> result = new ArrayList<>();
if (start == null) return result;
Queue<GraphNode> queue = new LinkedList<>();
Set<GraphNode> visited = new HashSet<>();
long startTime = System.currentTimeMillis();
queue.offer(start);
visited.add(start);
while (!queue.isEmpty()) {
// 检查超时
if (System.currentTimeMillis() - startTime > timeoutMillis) {
System.out.println("BFS timeout after " + timeoutMillis + "ms");
break;
}
GraphNode current = queue.poll();
result.add(current.val);
for (GraphNode neighbor : current.neighbors) {
if (!visited.contains(neighbor)) {
visited.add(neighbor);
queue.offer(neighbor);
}
}
}
return result;
}
/**
* 并行BFS - 用于大规模图处理
*/
public static class ParallelBFS {
private final ExecutorService executor;
public ParallelBFS(int threadCount) {
this.executor = Executors.newFixedThreadPool(threadCount);
}
public List<Integer> parallelBFSTraversal(GraphNode start) {
// 简化的并行BFS实现思路
// 实际实现需要考虑更复杂的同步机制
List<Integer> result = Collections.synchronizedList(new ArrayList<>());
Queue<GraphNode> queue = new ConcurrentLinkedQueue<>();
Set<GraphNode> visited = ConcurrentHashMap.newKeySet();
queue.offer(start);
visited.add(start);
List<Future<?>> futures = new ArrayList<>();
while (!queue.isEmpty()) {
GraphNode current = queue.poll();
result.add(current.val);
// 并行处理邻居节点
for (GraphNode neighbor : current.neighbors) {
if (visited.add(neighbor)) {
queue.offer(neighbor);
}
}
}
return result;
}
}
}
6. 算法对比与选择指南
6.1 BFS vs DFS 深度对比
维度 | BFS | DFS |
数据结构 | 队列(FIFO) | 栈(LIFO) |
空间复杂度 | O(宽) - 可能很大 | O(深) - 通常较小 |
最短路径 | 保证找到最短路径 | 不一定是最短路径 |
完备性 | 是(如果解存在) | 是(在有限图中) |
适用场景 | 最短路径、层次遍历 | 拓扑排序、回溯、路径存在性 |
内存使用 | 较高(存储整层节点) | 较低(存储单条路径) |
实现复杂度 | 中等 | 简单(递归) |
6.2 场景选择指南
- 需要找到最短路径(无权图)
- 图比较浅但很宽
- 需要层次信息
- 解可能在较浅层级
- 内存受限
- 需要找到任何解(不要求最短)
- 图很深但较窄
- 需要回溯或记录路径
7. 常见陷阱与调试技巧
7.1 常见错误模式
// 错误1:忘记标记访问导致无限循环
public static List<Integer> mistake1_infiniteLoop(GraphNode start) {
List<Integer> result = new ArrayList<>();
Queue<GraphNode> queue = new LinkedList<>();
// 缺少: Set<GraphNode> visited = new HashSet<>();
queue.offer(start);
// 缺少: visited.add(start);
while (!queue.isEmpty()) {
GraphNode current = queue.poll();
result.add(current.val);
for (GraphNode neighbor : current.neighbors) {
// 缺少访问检查,会导致重复访问
queue.offer(neighbor);
}
}
return result;
}
// 错误2:访问标记时机错误
public static List<Integer> mistake2_lateMarking(GraphNode start) {
List<Integer> result = new ArrayList<>();
Queue<GraphNode> queue = new LinkedList<>();
Set<GraphNode> visited = new HashSet<>();
queue.offer(start);
// 应该在入队时标记,而不是出队时
while (!queue.isEmpty()) {
GraphNode current = queue.poll();
visited.add(current); // 太晚了!可能导致重复入队
result.add(current.val);
for (GraphNode neighbor : current.neighbors) {
if (!visited.contains(neighbor)) {
queue.offer(neighbor);
// 应该在这里: visited.add(neighbor);
}
}
}
return result;
}
}
7.2 调试与验证工具
* BFS调试工具类
*/
public class BFSDebugger {
/**
* 带日志的BFS,用于调试
*/
public static List<Integer> bfsWithDebug(GraphNode start) {
List<Integer> result = new ArrayList<>();
if (start == null) return result;
Queue<GraphNode> queue = new LinkedList<>();
Set<GraphNode> visited = new HashSet<>();
int step = 0;
queue.offer(start);
visited.add(start);
System.out.println("Step " + step + ": Enqueue " + start.val);
while (!queue.isEmpty()) {
GraphNode current = queue.poll();
result.add(current.val);
System.out.println("Step " + ++step + ": Process " + current.val);
for (GraphNode neighbor : current.neighbors) {
if (!visited.contains(neighbor)) {
visited.add(neighbor);
queue.offer(neighbor);
System.out.println("Step " + step + ": Enqueue neighbor " + neighbor.val);
}
}
}
return result;
}
/**
* 验证BFS结果的正确性
*/
public static boolean validateBFSResult(GraphNode start, List<Integer> result) {
if (start == null && result.isEmpty()) return true;
if (start == null || result.isEmpty()) return false;
// 检查起始节点
if (result.get(0) != start.val) return false;
// 检查访问顺序的层次性(简化验证)
Set<Integer> visited = new HashSet<>();
for (int nodeVal : result) {
if (visited.contains(nodeVal)) {
return false; // 重复访问
}
visited.add(nodeVal);
}
return true;
}
}
8. 总结与进阶学习
8.1 核心要点回顾
- BFS本质:层次遍历,保证最短路径(无权图)
- 实现关键:队列 + 访问标记
- 时间复杂度:O(V + E)
- 空间复杂度:O(V)
- 适用场景:最短路径、连通分量、层次遍历
8.2 进阶学习路径
- 加权图BFS:学习Dijkstra算法
- 启发式搜索:掌握A*算法
- 并行BFS:了解分布式图处理
- 动态BFS:学习在动态图中的BFS
- 近似BFS:大规模图的近似算法
8.3 推荐练习题目
- LeetCode 102: 二叉树层次遍历
- LeetCode 107: 二叉树层次遍历II
- LeetCode 200: 岛屿数量
- LeetCode 127: 单词接龙
- LeetCode 279: 完全平方数
- LeetCode 542: 01矩阵
- LeetCode 1293: 网格中的最短路径
- LeetCode 773: 滑动谜题
- LeetCode 815: 公交路线