一起刷力扣之【200. 岛屿数量】

134 阅读1分钟

这是我参与2022首次更文挑战的第24天,活动详情查看:2022首次更文挑战

题目

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

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

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

示例

输入:grid = [  ["1","1","1","1","0"],
  ["1","1","0","1","0"],
  ["1","1","0","0","0"],
  ["0","0","0","0","0"]
]
输出:1
输入: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'的时候,以其为起点进行深度优先搜索,将搜索到的所有'1'都标记为'0',防止后面重复计算。这里需要注意的是题目给出的是字符数组,在判断的时候要判断字符'1',不能使用数字类型1

GIF 2022-2-11 16-57-00.gif

class Solution {
    private int m;
    private int n;

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

        // 全扫描
        for(int x = 0; x < m; ++x){
            for(int y = 0; y < n; ++y){
                // 判断是否为岛屿
                if(grid[x][y] == '1'){
                    // 岛屿数量 +1
                    ++land;
                    // 深度优先搜索
                    dfs(grid, x, y);
                }
            }
        }
        return land;
    }

    private void dfs(char[][] grid, int x, int y){
        // 边界判断
        if(x >= m || x < 0 || y >= n || y < 0 || grid[x][y] == '0'){
            return;
        }

        // 重新标记
        grid[x][y] = '0';
        // 搜索四周
        dfs(grid, x + 1, y);
        dfs(grid, x - 1, y);
        dfs(grid, x, y + 1);
        dfs(grid, x, y - 1);
    }
}

BFS

广度优先搜索跟深度优先搜索类似,都是先找到一个岛屿入口'1',再将其四周相连的岛屿加入队列中进行延申。

根据提示中的数值边界上限,我们可以把坐标轴的两个值进行计算优化成一个,这样就不需要新建一个数组来保存该坐标点,可以省略一些空间开销。

class Solution {
    private int m;
    private int n;
    private Queue<Integer> queue;
    public int numIslands(char[][] grid) {
        m = grid.length;
        n = grid[0].length;
        queue = new LinkedList<>();
        int land = 0;

        for(int x = 0; x < m; ++x){
            for(int y = 0; y < n; ++y){
                if(grid[x][y] == '1'){
                    ++land;
                    grid[x][y] = '0';
                    // 坐标计算优化
                    queue.add(x * 1000 + y);
                    bfs(grid);
                }
            }
        }

        return land;
    }

    private void bfs(char[][] grid){
        while(!queue.isEmpty()){
            int num = queue.poll();
            // 将数值反推得到坐标轴
            int xx = num / 1000;
            int yy = num % 1000;
            if(xx - 1 >= 0 && grid[xx - 1][yy] == '1'){
                queue.add((xx - 1) * 1000 + yy);
                grid[xx - 1][yy] = '0';
            }
            if(xx + 1 < m && grid[xx + 1][yy] == '1'){
                queue.add((xx + 1) * 1000 + yy);
                grid[xx + 1][yy] = '0';
            }
            if(yy - 1 >= 0 && grid[xx][yy - 1] == '1'){
                queue.add(xx * 1000 + yy - 1);
                grid[xx][yy - 1] = '0';
            }
            if(yy + 1 < n && grid[xx][yy + 1] == '1'){
                queue.add(xx * 1000 + yy + 1);
                grid[xx][yy + 1] = '0';
            }
        }
    }
}