LeetCode 200. 岛屿数量——DFS 连通块模板彻底讲透

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 模板

终止条件

  1. 越界
  2. 遇到海水
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 的启动次数就是岛屿的数量。