【剑指Offer-DFS】统计封闭岛屿的数目

题目描述

有一个二维矩阵 grid ,每个位置要么是陆地(记号为 0 )要么是水域(记号为 1 )。

我们从一块陆地出发,每次可以往上下左右 4 个方向相邻区域走,能走到的所有陆地区域,我们将其称为一座「岛屿」。

如果一座岛屿 完全 由水域包围,即陆地边缘上下左右所有相邻区域都是水域,那么我们将其称为 「封闭岛屿」。

请返回封闭岛屿的数目。

示例:

输入: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 区域包围)。

题目链接: https://leetcode-cn.com/problems/number-of-closed-islands/

思路

使用 dfs 来做。封闭岛屿就是岛屿的点都不在数组的边界上。例如,假如 grid 是 5 行 5 列的,那么如果岛屿范围在 1~3 行和 1~3 列之间,那么这个岛屿就是封闭的。相反,如果岛屿的一个点在 grid 的边界上,例如岛屿的一个点的位置为 grid[0][1],那么这个岛屿就不是封闭的。

所以,我们先 dfs 出岛屿的形状,然后在 dfs 过程中判断岛屿的某个位置是否出现在了边界上,如果都没有出现在边界上,那么我们就找到了一个封闭岛屿。

代码如下:

class Solution {
    bool flag = true;
    int dirs[4][2] = {{0,1},{1,0},{-1,0},{0,-1}};
public:
    int closedIsland(vector<vector<int>>& grid) {
        if(grid.empty()) return 0;

        int cnt = 0;
        for(int i=0; i<grid.size(); i++){
            for(int j=0; j<grid[i].size(); j++){
                flag = true; // 表示当前岛屿是否是封闭岛屿
                if(grid[i][j]==0){
                    dfs(grid, i, j);
                    if(flag) cnt++;
                }
            }
        }
        return cnt;
    }

    void dfs(vector<vector<int>>& grid, int r, int c){
        if(r==0 || r==grid.size()-1 || c==0 || c==grid[0].size()-1) flag = false; // 出现在了grid的边界,不是封闭岛屿,但还是要接着把岛屿形状dfs完成,不能return

        for(int i=0; i<4; i++){
            int nr = r+dirs[i][0];
            int nc = c+dirs[i][1];
            if(nr>=0 && nr<grid.size() && nc>=0 && nc<grid[0].size() && grid[nr][nc]==0){
                grid[nr][nc] = 2;
                dfs(grid, nr, nc);
            }
        }
    }
};
posted @ 2020-07-13 15:16  Flix  阅读(259)  评论(0编辑  收藏  举报