LeetCode 200. 岛屿数量------DFS 连通块模板彻底讲透
一、题目描述
给定一个由 '1'(陆地)和 '0'(海水)组成的二维网格,计算网格中岛屿的数量。
规定:
- 岛屿只能由上下左右四个方向连接形成;
- 四周都被海水包围;
- 返回岛屿的总数量。
示例:
text
输入:
[
["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]
]
输出:3
二、核心思想
这道题本质上是在求:
二维网格中有多少个连通块。
遇到一个新的陆地:
python
grid[i][j] == "1"
说明发现了一座新的岛屿:
python
count += 1
然后利用 DFS,把这座岛屿的所有陆地全部访问一遍,并标记成已经访问过。
这样后面再次遍历到这些位置时,就不会重复计数。
三、DFS 为什么能解决这道题
例如:
text
1 1 0
1 0 0
0 0 1
当遍历到:
text
(0,0)
时:
python
count = 1
然后 DFS 会把:
text
1 1
1
全部淹没:
text
0 0 0
0 0 0
0 0 1
继续遍历:
发现:
text
(2,2)
又是一座新的岛:
python
count = 2
最终返回:
python
2
四、DFS 模板
终止条件
- 越界
- 遇到海水
python
if i < 0 or i >= m or j < 0 or j >= n:
return
if grid[i][j] == "0":
return
标记当前节点已经访问
python
grid[i][j] = "0"
四个方向继续搜索
python
dfs(i - 1, j)
dfs(i + 1, j)
dfs(i, j - 1)
dfs(i, j + 1)
五、完整代码
python
from typing import List
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
if not grid or not grid[0]:
return 0
m = len(grid)
n = len(grid[0])
count = 0
def dfs(i, j):
if i < 0 or i >= m or j < 0 or j >= n:
return
if grid[i][j] == "0":
return
grid[i][j] = "0"
dfs(i - 1, j)
dfs(i + 1, j)
dfs(i, j - 1)
dfs(i, j + 1)
for i in range(m):
for j in range(n):
if grid[i][j] == "1":
count += 1
dfs(i, j)
return count
六、复杂度分析
时间复杂度
text
O(m × n)
每个格子最多访问一次。
空间复杂度
text
O(m × n)
最坏情况下递归栈深度达到整个网格大小。
七、高频易错点
1、忘记判断越界
python
grid[i][j]
直接报错:
text
IndexError
2、忘记标记访问
python
grid[i][j] = "0"
会导致死递归。
3、忘记处理空网格
python
if not grid or not grid[0]:
return 0
否则:
python
len(grid[0])
直接报错。
八、DFS 连通块模板总结
遇到:
- 岛屿数量
- 最大岛屿面积
- 被围绕的区域
- 飞地数量
- 朋友圈
- 连通分量
几乎都是这个模板:
python
遍历所有节点
↓
发现新的陆地
↓
答案+1
↓
DFS淹没整块区域
九、一句话总结
遍历整个网格,每发现一个新的陆地,就利用 DFS 淹没整座岛屿,最终 DFS 的启动次数就是岛屿的数量。