统计封闭岛屿的数目
有一个二维矩阵 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 区域包围)
思路
解法一:
解题的关键在于如何判断 「封闭岛屿」。dfs思路如下:
- 如果遇到
0, 即陆地,则以此点进行扩散遍历,将访问过的节点置为1; - dfs遍历的时候需要判断是否和边界相连,如果相连则证明不是「封闭岛屿」,dfs遍历的结果为0;
- 累加「封闭岛屿」的结果。
class Solution {
public:
int m, n;
int closedIsland(vector<vector<int>>& grid) {
int res = 0;
m = grid.size();
n = grid[0].size();
for (int i = 0; i < m;i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 0) { // 陆地,开始遍历
res += dfs(grid, i, j);
}
}
}
return res;
}
int dfs(vector<vector<int>>& grid, int x, int y) {
if (x < 0 || x >= m || y < 0 || y >= n) {
return 0;
}
if (grid[x][y] == 1) { //碰到水域(值为1的点)就返回封闭岛屿个数1,表示该岛屿可能就是一个封闭岛屿
return 1;
}
grid[x][y] = 1;
// 如果碰到陆地(值为0的点)就继续向该陆地的四个方向遍历,同时将该陆地标记为1,表示这个位置已经遍历过了。
int vx[] = {0, 1, 0, -1};
int vy[] = {1, 0, -1, 0};
int res = 1;
for (int i = 0; i < 4; i++) {
res = min(res, dfs(grid, x + vx[i], y + vy[i])); // 四个方向进行遍历,去四个方向的最小值,若有一个为0,则到达边界,证明不是封闭岛屿
}
return res;
}
};
解法二
也可以使用 BFS 方法,思路如下:
- 将当前陆地的位置加入到队列中,然后取出当前位置,并将它标记为1,表示它已经遍历过了;
- 将它四个方向也为陆地的位置加入到队列中,一直循环,直到队列为空;
- 在循环的过程中我们需要判断是否走出了边界,如果走出了边界就说明该位置所在的岛屿不是封闭岛屿。
class Solution {
public:
int m, n;
int closedIsland(vector<vector<int>>& grid) {
int res = 0;
m = grid.size();
n = grid[0].size();
for (int i = 0; i < m;i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 0) {
res += bfs(grid, i, j);
}
}
}
return res;
}
int bfs(vector<vector<int>> &grid, int x, int y)
{
int res = 1;
queue<vector<int>> q;
q.push({x, y});
while (!q.empty())
{
vector<int> pos(q.front());
q.pop();
grid[pos[0]][pos[1]] = 1;
int vx[] = {0, 1, 0, -1};
int vy[] = {1, 0, -1, 0};
for (int i = 0; i < 4; i++)
{
int nx = pos[0] + vx[i];
int ny = pos[1] + vy[i];
if (nx < 0 || nx >= m || ny < 0 || ny >= n)
{ // 若达到边界上,则证明不是封闭岛屿
res = 0;
continue;
}
if (grid[nx][ny] == 0)
{ // 将其他邻近的陆地添加到队列中
q.push({nx, ny});
}
}
}
return res;
}
};