【算法题解】53. 统计封闭岛屿的数目

这是一道 「中等难度」 的题
https://leetcode.cn/problems/number-of-closed-islands/

题目

二维矩阵 grid(土地)和 (水)组成。岛是由最大的 个方向连通的 组成的群,封闭岛是一个 「完全」 包围(左、上、右、下)的岛。

请返回 封闭岛屿 的数目。

示例 1:【算法题解】53. 统计封闭岛屿的数目

输入:grid =[
      [1,1,1,1,1,1,1,0],
            [1,0,0,0,0,1,1,0],
            [1,0,1,0,1,1,1,0],
            [1,0,0,0,0,1,0,1],
            [1,1,1,1,1,1,1,0]
     ] 
输出:2
解释: 灰色区域的岛屿是封闭岛屿,因为这座岛屿完全被水域包围(即被 1 区域包围)。

示例 2:【算法题解】53. 统计封闭岛屿的数目

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

示例 3:

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

提示:

  • ,

题解

求岛屿数量也就是求数值为 0 的连通块。思路为遍历二维数组中的每一个元素,如果遇到 0 ,就说明遇到了岛屿,答案计数加一,然后一定要记得将这个岛屿覆盖到的所有 0 设置为 1 或其他 非0 的值,以免导致重复计数。

还有一点需要注意的是,题目要求的是 封闭岛屿,也就是不能包含挨着边界的外部连通块,所以在求内部连通块个数前可以先将外部连通块清除掉,清除方式同样是将所有 0 设置为 1

如何将岛屿覆盖到的所有 ‘0’ 设置为 ‘1’ 呢?

首先将当前位置 0 设置为 1,然后再将挨着这个位置的 「上下左右」 4个位置的 0 设置为 1,重复此步骤,每一步的处理逻辑都是一样的,又是典型的 「递归」 的思路。

递归函数: 将当前位置 0 设置为 1,然后再递归上下左右4个位置。

边界条件: 有两种可能,分别是:

  • 或者 出界,返回。
  • ,返回。

翻译成代码,以 Java 为例

// 递归函数,i 和 j 为当前位置的坐标
private void resetZero(int[][] grid, int i, int j){

    // 边界条件
    if(i < 0 || i >= grid.length){
        return;
    }
    if(j < 0 || j >= grid[0].length){
        return;
    }
    if(grid[i][j] == 1){
        return;
    }
        
  // 将当前位置设置为1
    grid[i][j] = 1;

    // 递归 上下左右 4个位置
    resetZero(grid, i + 1, j, m, n);
    resetZero(grid, i - 1, j, m, n);
    resetZero(grid, i, j + 1, m, n);
    resetZero(grid, i, j - 1, m, n);
}

综上,总体思路为:

  1. 循环遍历 4 条边,遇到 0 就使用递归函数 将这个 0 所属于的外部连通块清除掉。
  2. 循环遍历 4 条边以内的所有点,遇到 0 就将答案 ans 加一,并将这个 0 所属于的内部连通块清除掉。

Java 代码实现

class Solution {
    public int closedIsland(int[][] grid) {
        // 先把边上的0和其联通的消除掉
        
        int m = grid.length;
        int n = grid[0].length;
        
        for(int i = 0; i < m; i++){
            // i = 0 或者 i = m - 1 或者 j = 0 或者 j = n - 1 时是边
            int step =  i == 0 || i == m - 1 ? 1 : n - 1;
            for(int j = 0; j < n; j += step){
                resetZero(grid, i, j);
            }
        }

        int ans = 0;
        for(int i = 1; i < m - 1; i++){
            for(int j = 1; j < n - 1; j++){
                // 遇到 0,答案就+1;
                // 然后将这个岛清除掉
                if(grid[i][j] == 0){
                    ans++;
                    resetZero(grid, i, j);
                }
            }
        }
        return ans;
    }

    private void resetZero(int[][] grid, int i, int j){

        if(i < 0 || i >= grid.length){
            return;
        }
        if(j < 0 || j >= grid[0].length){
            return;
        }
        if(grid[i][j] == 1){
            return;
        }
        

        grid[i][j] = 1;
        resetZero(grid, i + 1, j);
        resetZero(grid, i - 1, j);
        resetZero(grid, i, j + 1);
        resetZero(grid, i, j - 1);
    }
}

Go 代码实现

func closedIsland(grid [][]int) int {
    m, n := len(grid), len(grid[0])

    for i := 0; i < m; i++ {
        step := 1
        if i != 0 && i != m - 1 {
            step = n - 1
        }
        for j := 0; j < n; j += step {
            resetZero(grid, i, j)
        }
    }

    ans := 0
    for i := 1; i < m - 1; i++ {
        for j := 1; j < n - 1; j++ {
            if grid[i][j] == 0 {
                ans++
            }
            resetZero(grid, i, j)
        }
    }

    return ans
}

func resetZero(grid [][]int, i int, j int) {
    m, n := len(grid), len(grid[0])
    if i < 0 || i >= m || j < 0 || j >= n {
        return
    }
    if grid[i][j] == 1 {
        return
    }

    grid[i][j] = 1

    resetZero(grid, i + 1, j)
    resetZero(grid, i - 1, j)
    resetZero(grid, i, j - 1)
    resetZero(grid, i, j + 1)

}

复杂度分析

时间复杂度: MN 分别为二维矩阵的高度和宽度。矩阵中的每一个为 1 的点都需要遍历 1 次。每个为 0 的点需要遍历最多两次,一次是将 0 改为 1,一次是按顺序遍历检查是否是 0

空间复杂度: MN 分别为二维矩阵的高度和宽度。空间复杂度取决于递归调用栈的深度,最大为 MN,即举矩阵中都是 0 的时候。


– End –


【算法题解】53. 统计封闭岛屿的数目
如果觉得有所收获,就顺道点个关注吧!【算法题解】53. 统计封闭岛屿的数目 

原文始发于微信公众号(i余数):【算法题解】53. 统计封闭岛屿的数目

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/193659.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!