200 岛屿数量

一、题目

给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。

二、题解

“沉岛思想”(深度优先搜索(DFS)):

  • 扫描找岛:用两层循环从左到右、从上到下扫视网格。
  • 发现计数:只要碰到 '1'(陆地),就说明发现了一座新岛屿,总数立刻 +1
  • 沉岛去重(DFS):为了防止这块岛屿以后被重复计算,立马从这个 '1' 开始,把和它连在一起的所有 '1' 全都变成 '0'(水)。
class Solution {
    public int numIslands(char[][] grid) {
        // 边界条件判断:如果网格为空,直接返回 0
        if (grid == null || grid.length == 0) {
            return 0;
        }

        int rows = grid.length;
        int cols = grid[0].length;
        int islandCount = 0; // 用于记录岛屿的数量

        // 遍历整个二维网格
        for (int r = 0; r < rows; ++r) {
            for (int c = 0; c < cols; ++c) {
                // 如果当前遇到了陆地 '1'
                if (grid[r][c] == '1') {
                    islandCount++; // 发现新岛屿,数量 +1
                    // 启动 DFS,将这座岛屿的所有陆地“沉没”(变成 '0')
                    dfs(grid, r, c);
                }
            }
        }

        return islandCount;
    }

    // 深度优先搜索辅助函数
    private void dfs(char[][] grid, int r, int c) {
        int rows = grid.length;
        int cols = grid[0].length;

        // 【跳出递归的条件】
        // 1. 越界(r 或 c 超出网格范围)
        // 2. 遇到了水('0'),或者已经访问过的陆地
        if (r < 0 || c < 0 || r >= rows || c >= cols || grid[r][c] == '0') {
            return;
        }

        // 将当前陆地标记为水('0'),表示已经访问过,防止死循环和重复计算
        grid[r][c] = '0';

        // 继续向四个方向深度优先搜索寻找相连的陆地
        dfs(grid, r - 1, c); // 向上
        dfs(grid, r + 1, c); // 向下
        dfs(grid, r, c - 1); // 向左
        dfs(grid, r, c + 1); // 向右
    }
}

时间复杂度O(m×n)O(m \times n)

空间复杂度O(m×n)O(m \times n)

评论