leetcode 1254. Number of Closed Islands(岛的数量)

在这里插入图片描述
0代表陆地,1代表水,上下左右都被水包围的陆地才叫一个岛。
数组边界外面的不算。
问有多少个岛。

思路:

这种求连通区域的一般用DFS。
leetcode.200题很像,区别是200题默认数组边界外面都是水,所以只要有陆地,至少就会有一个岛出现,只需要找出所有连通的陆地。

而本题不算边界外面,如果是陆地连着数组边界,那就不算岛。
所以如果行或列 < 3,肯定形不成岛。

既然边界部分的一圈不能被水包围,也就不能形成岛,所以边界的一圈不考虑,
DFS只对1 ~ row-2, 1 ~ col-2部分操作。

DFS终止条件:如果到了边界的一圈,肯定不能形成岛,需要返回false.
如果四周都是水, 或者四周都已经访问过,返回true.
当上下左右都是true时,才能形成封闭的岛。

注意
最后可以写成left && right && up && down, 但不能把4个dfs写在一起,即dfs && dfs && dfs && dfs的形式。
dfs函数要一个一个计算,不能拼在一个逻辑式里面计算,否则有的case会得到错误的结果。
分析原因,几个dfs && 运算内部不得而知,估计是有并行计算的,而visited数组的修改并不是线程安全的,
多个dfs一起计算时可能有的visited在不恰当的时机被修改了,从而得到错误的true和false.

class Solution {
    int rows = 0;
    int cols = 0;
    //boolean[][] visited;
    
    public int closedIsland(int[][] grid) {
        rows = grid.length;
        cols = grid[0].length;
        //visited = new boolean[rows][cols];
        int res = 0;

        if(rows < 3 || cols < 3) return 0;

        for(int r = 1; r < rows-1; r++) {
            for(int c = 1; c < cols-1; c++) {
                //if(grid[r][c]==1 || visited[r][c]) continue;
                if(grid[r][c] == 0) 
                   if(dfs(grid, r, c)) res ++;
            }
        }
        return res;
    }

    boolean dfs(int[][] grid, int r, int c) {
        //if(visited[r][c] || grid[r][c] == 1) return true;
        if(grid[r][c] == -1 || grid[r][c] == 1) return true;
        if(r <= 0 || c <= 0 || r >= rows-1 || c >= cols-1) return false;
        
        grid[r][c] = -1;
        //visited[r][c] = true;

        boolean left = dfs(grid, r,c-1);
        boolean right = dfs(grid, r, c+1);
        boolean up = dfs(grid, r-1, c);
        boolean down = dfs(grid, r+1, c);
        //注意:不要写成dfs(grid, r,c-1) && dfs(grid, r, c+1) && dfs(grid, r-1, c) && dfs(grid,r+1,c)!
        
        return left && right && up && down;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝羽飞鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值