Skip to content

岛屿数量

约 856 字大约 3 分钟

DFSBFS

2025-02-25

200. 岛屿数量

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

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

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

示例 1:

输入:grid = [
  ["1","1","1","1","0"],
  ["1","1","0","1","0"],
  ["1","1","0","0","0"],
  ["0","0","0","0","0"]
]
输出:1

示例 2:

输入:grid = [
  ["1","1","0","0","0"],
  ["1","1","0","0","0"],
  ["0","0","1","0","0"],
  ["0","0","0","1","1"]
]
输出:3

提示:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 300
  • grid[i][j] 的值为 '0''1'

DFS淹没相邻的1

每发现一个岛屿,岛屿数量加一,然后使用 DFS 将岛屿淹了,dfs就四件事:检查特殊情况,执行本次操作,进入下一层递归,返回。

class Solution {
    // 主函数,计算岛屿数量
    public int numIslands(char[][] grid) {
        int res = 0;
        int m = grid.length, n = grid[0].length;
        
        // 遍历 grid
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == '1') {
                    // 每发现一个岛屿,岛屿数量加一
                    res++;
                    // 然后使用 DFS 将岛屿淹了
                    dfs(grid, i, j);
                }
            }
        }
        
        return res;
    }

    // 从 (i, j) 开始,将与之相邻的陆地都变成海水。
    // 特殊值,操作,进入子递归。
    void dfs(char[][] grid, int i, int j) {
        int m = grid.length, n = grid[0].length;
        // 超出索引边界
        if (i < 0 || j < 0 || i >= m || j >= n) {
            return;
        }
        // 已经是海水了
        if (grid[i][j] == '0') {
            return;
        }
        
        // 将 (i, j) 变成海水
        grid[i][j] = '0';
        // 淹没上下左右的陆地
        dfs(grid, i + 1, j);
        dfs(grid, i, j + 1);
        dfs(grid, i - 1, j);
        dfs(grid, i, j - 1);
    }
}
  • 时间复杂度:O(MN),其中 M 和 N 分别为行数和列数。
  • 空间复杂度:O(MN),在最坏情况下,整个网格均为陆地,深度优先搜索的深度达到 MN。

BFS淹没相邻的1

入队前淹没不会超时。无条件入队,出队后再淹没会超时。

class Solution {
    public int numIslands(char[][] grid) {
        int m = grid.length;
        int n = grid[0].length;
        int ans = 0;

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == '1') {
                    bfs(grid, m, n, i, j);
                    ans++;
                }
            }
        }
        return ans;
    }

    public void bfs(char[][] grid, int m, int n, int i, int j) {
        Queue<int[]> q = new LinkedList<>();

        q.offer(new int[] { i, j });
        // 对当前位置的操作:变为0
        grid[i][j] = '0';
        while (!q.isEmpty()) {
            int[] a = q.poll();
            int x = a[0];
            int y = a[1];

            int[][] dir = new int[][] { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };
            for (int k = 0; k < 4; k++) {
                int newX = x + dir[k][0];
                int newY = y + dir[k][1];

                // 把与当前1相邻的1都加进去。队列里只存1。
                // 对相邻位置的操作,变为0+入队。
                if (newX >= 0 && newX < m && newY >= 0 && newY < n && grid[newX][newY] == '1') {
                    q.offer(new int[] { newX, newY });
                    grid[newX][newY] = '0';
                }
            }
        }
        return;
    }
}

超时:

class Solution {
    public int numIslands(char[][] grid) {
        int m = grid.length;
        int n = grid[0].length;
        int ans = 0;

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == '1') {
                    bfs(grid, m, n, i, j);
                    ans++;
                }
            }
        }
        return ans;
    }

    public void bfs(char[][] grid, int m, int n, int i, int j) {
        Queue<int[]> q = new LinkedList<>();

        q.offer(new int[] { i, j });
        while (!q.isEmpty()) {
            int[] a = q.poll();
            int x = a[0];
            int y = a[1];
            grid[x][y] = '0';

            int[][] dir = new int[][] { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };
            for (int k = 0; k < 4; k++) {
                int newX = x + dir[k][0];
                int newY = y + dir[k][1];

                if (newX >= 0 && newX < m && newY >= 0 && newY <= n && grid[newX][newY] == '1') {
                    q.offer(new int[] { newX, newY });
                }
            }
        }
        return;
    }
}