二维网格 + 上下左右 + 连通区域
一眼 BFS / DFS 题,但真正吃透后,能解决一整类问题。
一、题目简介
给你一个由 '1'(陆地)和 '0'(水)组成的二维网格 grid,请你计算网格中 岛屿的数量。
岛屿定义
'1'表示陆地'0'表示水- 上、下、左、右相邻的陆地视为同一座岛屿
- 对角线不算相邻
二、问题本质:不是“数 1”,而是“数连通块”
很多人第一反应是:
“遍历数组,遇到
1就加一?”
❌ 这是错误的直觉。
正确的理解应该是:
每一座岛屿 = 一整块相互连通的
1
所以问题本质是:
👉 二维网格中的连通分量数量
三、核心思想:BFS + 洪水填充(Flood Fill)
一句话总结思路
每当遇到一个
1,就用 BFS 把它所在的整座岛屿“淹掉”。
流程拆解如下:
-
遍历整个网格
-
遇到
'1':- 说明发现了一座新岛屿
- 岛屿数量
+1
-
以该点为起点,使用 BFS 向四周扩散
-
将所有相连的
'1'全部标记为'0' -
继续扫描剩余网格
四、为什么选择 BFS?
-
BFS 非常适合:
- 从一个点向四周扩散
- 层层推进
-
相比 DFS 递归:
- BFS 不存在 Java 栈溢出风险
- 更贴近“洪水漫延”的直觉
👉 工程实践中,BFS 更安全、更稳。
五、代码实现(BFS 标准写法)
下面是完整实现,逻辑非常清晰 👇
class Solution {
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0) {
return 0;
}
int res = 0;
int row = grid.length;
int col = grid[0].length;
Queue<int[]> queue = new LinkedList<>();
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (grid[i][j] == '1') {
res++;
queue.add(new int[]{i, j});
grid[i][j] = '0';
while (!queue.isEmpty()) {
int[] cur = queue.poll();
int x = cur[0];
int y = cur[1];
if (x - 1 >= 0 && grid[x - 1][y] == '1') {
queue.add(new int[]{x - 1, y});
grid[x - 1][y] = '0';
}
if (y - 1 >= 0 && grid[x][y - 1] == '1') {
queue.add(new int[]{x, y - 1});
grid[x][y - 1] = '0';
}
if (x + 1 < row && grid[x + 1][y] == '1') {
queue.add(new int[]{x + 1, y});
grid[x + 1][y] = '0';
}
if (y + 1 < col && grid[x][y + 1] == '1') {
queue.add(new int[]{x, y + 1});
grid[x][y + 1] = '0';
}
}
}
}
}
return res;
}
}
六、几个非常关键的细节(面试常问)
1️⃣ 为什么一入队就标记为 '0'?
queue.add(new int[]{i, j});
grid[i][j] = '0';
这是 BFS 的标准写法:
- 防止同一个节点被多次入队
- 保证每个格子只被访问一次
👉 “入队即标记” 是 BFS 的核心习惯
2️⃣ 为什么用 Queue 而不是 Stack?
- Queue → BFS(广度优先)
- Stack / 递归 → DFS(深度优先)
这道题中:
- BFS / DFS 都能做
- BFS 在 Java 中 更安全
3️⃣ 为什么用 !queue.isEmpty() 而不是 queue.size() > 0?
while (!queue.isEmpty()) { ... }
原因:
- 语义更清晰(判断是否为空)
- 更符合 Java 集合接口的设计初衷
- 也是业界规范写法
七、时间 & 空间复杂度分析
⏱️ 时间复杂度
- 每个格子最多访问一次
👉 O(row × col)
🧠 空间复杂度
- 队列最坏情况下存整座岛屿
👉 O(row × col)
八、如何一眼识别这是 BFS / DFS 题?
看到这些关键词,直接条件反射:
- 二维矩阵 / 网格
- 上下左右
- 连通 / 区域 / 块
- 访问过就不能重复访问
👉 90% 都是 Flood Fill 模型
九、一句话总结
岛屿数量问题,本质不是“数 1”,
而是“发现一个 1,就用 BFS 消灭它所在的整块区域”。