LeetCode Notes_#200 岛屿数量

LeetCode Notes_#200 岛屿数量

Contents

题目

给你一个由'0'(水)和'1'(陆地)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。

示例1:
输入:

[
['1','1','1','1','0'],
['1','1','0','1','0'],
['1','1','0','0','0'],
['0','0','0','0','0']
]
输出: 1

示例2:

输入:
[
['1','1','0','0','0'],
['1','1','0','0','0'],
['0','0','1','0','0'],
['0','0','0','1','1']
]
输出: 3
解释: 每座岛屿只能由水平和/或竖直方向上相邻的陆地连接而成。

思路分析

一个岛屿是由一些在上下左右方向上相邻的'1'所构成的。我们在计数的时候,只需要计数每一个岛屿里第一次访问的'1'就行了。然后就往上下左右四个方向进行搜索,直到遇到grid的边界,或者遇到水面'0'。
搜索有两种方法,DFS和BFS。
需要特别注意的一点是,在辅助函数dfs/bfs当中,需要把访问到的'1'元素置为'0',防止在主循环当中访问第二次。

解答

方法1:DFS

class Solution {
    public int numIslands(char[][] grid) {
        int count = 0;
        //主循环
        for(int i = 0;i <= grid.length - 1;i++){
            for(int j = 0;j <= grid[0].length - 1;j++){
                //遇到一个位置是陆地('1'),那么使用dfs搜索它的边界
                if(grid[i][j] == '1'){
                    dfs(grid, i, j);
                    //然后计数器增加1
                    count++;
                }
            }
        }
        return count;
    }

    private void dfs(char[][] grid, int i, int j){
        //遇到水面('0')或者是网格的边界,就停止搜索
        if(i < 0 || i >= grid.length || j < 0 || j >= grid[0].length || grid[i][j] == '0') return;
        //一个岛屿当中只有在主循环里第一次访问的'1'需要计数,所以将访问完的元素置为'0',避免重复计数
        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是gird网格的行数和列数。
空间复杂度:O(MN),如果整个矩阵都是陆地'1',那么递归调用了MN次,占用的系统栈深度是O(MN)

方法2:BFS

class Solution {
    public int numIslands(char[][] grid) {
        int count = 0;
        //主循环
        for(int i = 0;i <= grid.length - 1;i++){
            for(int j = 0;j <= grid[0].length - 1;j++){
                //遇到一个位置是陆地('1'),那么使用bfs搜索它的边界
                if(grid[i][j] == '1'){
                    bfs(grid, i, j);
                    //然后计数器增加1
                    count++;
                }
            }
        }
        return count;
    }

    private void bfs(char[][] grid, int i, int j){
        Queue<int[]> queue = new LinkedList<>();
        //放入一个岛屿中首次被访问的'1'的坐标
        queue.offer(new int[]{i,j});
        while(!queue.isEmpty()){
            int[] cur = queue.poll();
            i = cur[0];
            j = cur[1];
            if(i >= 0 && i <= grid.length - 1 && j >= 0 && j <= grid[0].length - 1 && grid[i][j] == '1'){
                grid[i][j] = '0';
                queue.offer(new int[]{i + 1,j});
                queue.offer(new int[]{i,j + 1});
                queue.offer(new int[]{i - 1,j});
                queue.offer(new int[]{i,j - 1});
            }
        }
    }
}

复杂度分析

时间复杂度:O(MN)
空间复杂度:O(min(M,N)),不知道是如何分析的...

posted @ 2020-09-03 20:07  Howfar's  阅读(148)  评论(0编辑  收藏  举报