https://leetcode.cn/problems/number-of-closed-islands/
二维矩阵 grid 由 0 (土地)和 1 (水)组成。岛是由最大的4个方向连通的 0 组成的群,封闭岛是一个 完全 由1包围(左、上、右、下)的岛。
请返回 封闭岛屿 的数目。
示例 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 区域包围)。
class Solution:
def closedIsland(self, grid: List[List[int]]) -> int:
# 解题包括3个部分:1、定义淹没函数,2、淹没周边陆地,3、两层for循环
# 如何判断封闭岛屿?把200题中靠边的岛屿排除掉,剩下的就是封闭岛屿
# 如何排除?把四边的陆地及其上下左右淹没成海洋,这样在主循环中就不会去操作了
m, n = len(grid), len(grid[0])
def dfs(i, j):
# 递归函数终止条件:1、越界,2、已是海洋
if not 0 <= i < m or not 0 <= j < n:
return
if grid[i][j] == 1:
return
grid[i][j] = 1 # 将(i, j)变成海水
dfs(i - 1, j) # 上(包括上的上下左右,所有递归)
dfs(i + 1, j) # 下(包括下的上下左右,所有递归)
dfs(i, j - 1) # 左(包括左的上下左右,所有递归)
dfs(i, j + 1) # 右(包括右的上下左右,所有递归)
# def bfs(i, j):
# q = [[i, j]]
# while q:
# [i, j] = q.pop(0)
# if not 0 <= i < m or not 0 <= j < n:
# continue
# if grid[i][j] == 1:
# continue
# grid[i][j] = 1
# q += [[i - 1, j], [i + 1, j], [i, j - 1], [i, j + 1]]
for i in range(m):
dfs(i, 0) # 把所有与最左列陆地相连的陆地(包括最左列)都淹掉
dfs(i, n - 1) # 把所有与最右列陆地相连的陆地(包括最右列)都淹掉
for j in range(n):
dfs(0, j) # 把所有与首行陆地相连的陆地(包括首行)都淹掉
dfs(m - 1, j) # 把所有与最下行陆地相连的陆地(包括最下行)都淹掉
# 通过以上2个淹没遍历,会把所有与边界相连的岛屿全部淹没
# 剩下遍历的都是封闭岛屿
cnt = 0
for i in range(m):
for j in range(n):
if grid[i][j] == 0: # 遇到陆地
cnt += 1 # 岛屿+1
dfs(i, j) # 淹没之
# bfs(i, j)
return cnt