# [1254] 统计封闭岛屿的数目

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

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

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

请返回封闭岛屿的数目。

示例 1:

输入: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:

输入: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

提示:

1 <= grid.length, grid[0].length <= 100 0 <= grid[i][j] <=1

这道题是 [200] 岛屿数量 岛屿问题的变种,只是求解变为了不在边界上的岛屿数量。

那么解决思路也很简单,我们先淹没掉在边界上的岛屿,在开始计数就行了。

function closedIsland(grid: number[][]): number {
  let res = 0;
  const width = grid[0].length;
  const height = grid.length;

  // 先淹没掉四周的岛屿
  for (let i = 0; i < height; i++) {
    // 左右两侧岛屿淹没
    floodFill(i, 0);
    floodFill(i, width - 1);
  }
  for (let j = 0; j < width; j++) {
    // 上下两侧岛屿淹没
    floodFill(0, j);
    floodFill(height - 1, j);
  }

  // 在查询中间的岛屿,并增加计数器
  for (let i = 1; i < height - 1; i++) {
    for (let j = 1; j < width - 1; j++) {
      if (grid[i][j] === 0) {
        res += 1;
        floodFill(i, j);
      }
    }
  }

  return res;

  function floodFill(i: number, j: number) {
    // 越界返回
    if (i < 0 || i >= height || j < 0 || j >= width) return;
    // 已遍历过,或者不为陆地,返回
    if (grid[i][j] === 1) return;

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