200. 岛屿数量

200. 岛屿数量

✨核心逻辑

本题采用 深度优先搜索(DFS) + 沉岛策略 的方法:

  1. 边界判断:如果网格为空,直接返回 0。
  2. 遍历寻找岛屿:遍历二维数组的每一个位置。当遇到一个 '1' 时,说明发现了一个新的岛屿,岛屿数量 count 加 1。
  3. DFS 标记淹没:对发现的岛屿位置立即启动 DFS 递归,向该位置的上下左右四个方向进行搜索。将所有与当前陆地相连通的 '1' 全部修改为 '0'(即“沉没”)。
  4. 避免重复计数:通过“沉没”操作,后续遍历中这些相连的陆地就已经变成了水域,从而避免重复计算同一个岛屿。

🔥代码实现(含详细变量注释)

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。

    🔍总结一下