题目描述
有一个二维矩阵 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);
}
}
}
};