200. 岛屿数量
✨核心逻辑
本题采用 深度优先搜索(DFS) + 沉岛策略 的方法:
- 边界判断:如果网格为空,直接返回 0。
- 遍历寻找岛屿:遍历二维数组的每一个位置。当遇到一个
'1'时,说明发现了一个新的岛屿,岛屿数量count加 1。 - DFS 标记淹没:对发现的岛屿位置立即启动 DFS 递归,向该位置的上下左右四个方向进行搜索。将所有与当前陆地相连通的
'1'全部修改为'0'(即“沉没”)。 - 避免重复计数:通过“沉没”操作,后续遍历中这些相连的陆地就已经变成了水域,从而避免重复计算同一个岛屿。
🔥代码实现(含详细变量注释)
class Solution {
public int numIslands(char[][] grid) {
// 边界情况判断:如果网格为空、行数为0、或者列数为0,直接返回 0
if (grid == null || grid.length == 0 || grid[0].length == 0) {
return 0;
}
// count:记录最终计算出的岛屿总数量
int count = 0;
// i:控制行遍历的外层循环指针
for (int i = 0; i < grid.length; i++) {
// j:控制列遍历的内层循环指针
for (int j = 0; j < grid[0].length; j++) {
// 如果当前位置是 '1',说明发现了一个全新的岛屿
if (grid[i][j] == '1') {
count++; // 岛屿数量加一
dfs(grid, i, j); // 递归处理,将该岛屿连通的陆地全部沉没
}
}
}
return count;
}
// 辅助函数:深度优先搜索
void dfs(char[][] grid, int i, int j) {
// 越界判断:如果行索引 i 或列索引 j 超出了网格的边界
// 或者当前格子是 '0'(代表已经被水淹没,或者本来就是水),则直接返回
if (i < 0 || j < 0 || i >= grid.length || j >= grid[0].length || grid[i][j] == '0') {
return;
}
// 核心沉岛操作:将当前的陆地 '1' 修改为 '0',防止在后续遍历中重复计算
grid[i][j] = '0';
// 向下、向上、向左、向右四个方向继续递归探索
dfs(grid, i - 1, j); // 探索上方
dfs(grid, i + 1, j); // 探索下方
dfs(grid, i, j - 1); // 探索左方
dfs(grid, i, j + 1); // 探索右方
}
}
⏱️复杂度分析
时间复杂度:O(M * N),其中 M 是网格的行数,N 是网格的列数。虽然我们在遍历时嵌套了 DFS 递归,但在整个算法执行过程中,每个格子(无论是 '1' 还是 '0')最多只会被访问和判断一次。
空间复杂度:O(M * N),主要消耗在 DFS 递归调用时系统隐式维护的栈空间。最坏情况下,整个网格全都是连成一片的陆地 '1',递归的深度将会达到 M * N。
🔍总结一下