飞地的数量-LeetCode
1020. 飞地的数量 - Number of Enclaves
🎯 问题描述(来源于LeetCode)
描述:
给定一个 m x n 的二维网格 grid,其中 1 表示陆地,0 表示水域。
如果一个陆地格子无法通过上下左右移动到网格边界(即被水域包围),则称为“飞地”。
返回飞地的数量(即所有满足条件的陆地格子数)。
说明:
- 移动只能在四方向上。
- 边界上的陆地不算飞地(因为它们可以走到边界)。
示例:
- 示例 1:
1 | 输入: grid = [[0,0,0,0],[1,0,1,0],[0,1,1,0],[0,0,0,0]] |
- 示例 2:
1 | 输入: grid = [[0,1,1,0],[0,0,1,0],[0,0,1,0],[0,0,0,0]] |
💻 解题思路
思路:从边界 DFS 标记所有可达陆地,再统计剩余陆地
算法步骤
- 获取网格尺寸
m, n。 - 定义 DFS 函数
dfs(i, j):- 如果坐标越界或当前格子不是陆地(
grid[i][j] != 1),则返回。 - 将当前格子标记为
0(表示已淹没)。 - 向四个方向递归调用
dfs。
- 如果坐标越界或当前格子不是陆地(
- 从所有边界格子出发:
- 遍历第一列和最后一列:如果
grid[i][0] == 1,则dfs(i, 0);如果grid[i][n-1] == 1,则dfs(i, n-1)。 - 遍历第一行和最后一行:如果
grid[0][j] == 1,则dfs(0, j);如果grid[m-1][j] == 1,则dfs(m-1, j)。 - 注意:四个角会被遍历两次,但不影响。
- 遍历第一列和最后一列:如果
- 经过上述操作,所有能到达边界的陆地都被标记为
0,剩下的1即为飞地。 - 返回剩余
1的总数:sum(sum(row) for row in grid)。
代码实现
1 | from typing import List |
📊 性能分析
- 时间复杂度:,每个格子最多被访问一次。
- 空间复杂度:,递归栈深度为连通区域大小,最坏 。
思考
- 本题的核心是逆向思维:不直接找被包围的陆地,而是从边界陆地出发,淹没所有能到达边界的陆地,剩下的就是飞地。
- 也可以使用 BFS 替代 DFS,避免递归深度过大。
- 注意:题目要求返回飞地的数量,即剩余
1的个数,而非布尔值。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 笺札!






