import collections
from typing import List, Deque, Tuple
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
"""
计算二维网格中岛屿的数量。
使用 BFS 辅助函数结构,并通过原地修改 grid 来标记已访问。
Args:
grid: 由 '1' (陆地) 和 '0' (水) 组成的二维列表。
注意:此方法会修改输入的 grid。
Returns:
岛屿的数量。
"""
if not grid or not grid[0]:
return 0
rows = len(grid)
cols = len(grid[0])
island_count = 0
# 方向数组,方便遍历邻居 (右, 左, 下, 上)
directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]
# 定义 BFS 辅助函数 (现在不需要 visited 参数)
def bfs(r: int, c: int):
"""
从 (r, c) 开始执行 BFS,将所有相连的陆地 '1' 修改为 '0'。
"""
queue: Deque[Tuple[int, int]] = collections.deque()
# 将起始点加入队列并立刻标记为已访问(改为 '0')
# (注意:调用此函数前已确认 grid[r][c] == '1')
queue.append((r, c))
grid[r][c] = '0'
while queue:
curr_r, curr_c = queue.popleft()
# 探索四个方向的邻居
for dr, dc in directions:
nr, nc = curr_r + dr, curr_c + dc
# 检查邻居是否有效且是陆地 ('1')
# 因为我们在入队时就修改,所以这里检查 '1' 就隐含了未访问
if (0 <= nr < rows and
0 <= nc < cols and
grid[nr][nc] == '1'):
# 将邻居加入队列
queue.append((nr, nc))
# 标记邻居为已访问 (改为 '0')
grid[nr][nc] = '0'
# --- 主函数逻辑 ---
# 遍历网格中的每个单元格
for r in range(rows):
for c in range(cols):
# 如果是陆地 ('1'),说明发现了一个新岛屿
# 因为 BFS 会将访问过的 '1' 改为 '0',所以这里无需额外的 visited 检查
if grid[r][c] == '1':
# 发现新岛屿
island_count += 1
# 调用 BFS “淹没”此岛屿的所有部分
bfs(r, c)
# 注意:此方法修改了原始 grid。如果需要保留原始 grid,
# 应在开始时创建 grid 的副本进行操作。
return island_count
# 示例用法
# solution = Solution()
# grid1 = [
# ["1","1","1","1","0"],
# ["1","1","0","1","0"],
# ["1","1","0","0","0"],
# ["0","0","0","0","0"]
# ]
# # 创建副本以防修改原 grid
# grid1_copy = [row[:] for row in grid1]
# print(solution.numIslands(grid1_copy)) # 输出: 1
# grid2 = [
# ["1","1","0","0","0"],
# ["1","1","0","0","0"],
# ["0","0","1","0","0"],
# ["0","0","0","1","1"]
# ]
# grid2_copy = [row[:] for row in grid2]
# print(solution.numIslands(grid2_copy)) # 输出: 3
def numIslands(self, grid: List[List[str]]) -> int:
"""
计算二维网格中岛屿的数量。
使用 DFS 递归辅助函数结构,并通过原地修改 grid 来标记已访问。
Args:
grid: 由 '1' (陆地) 和 '0' (水) 组成的二维列表。
注意:此方法会修改输入的 grid。
Returns:
岛屿的数量。
"""
if not grid or not grid[0]:
return 0
rows = len(grid)
cols = len(grid[0])
island_count = 0
# 定义 DFS 辅助函数
def dfs(r: int, c: int):
"""
从 (r, c) 开始执行 DFS,将所有相连的陆地 '1' 修改为 '0'。
"""
# 1. 基准情况/停止条件:
# a. 检查是否越界
# b. 检查是否不是陆地 '1' (即 水 '0' 或 已访问过的标记 '0')
if not (0 <= r < rows and 0 <= c < cols) or grid[r][c] != '1':
return
# 2. 标记当前单元格为已访问 (原地修改)
grid[r][c] = '0'
# 3. 递归探索四个方向的邻居
dfs(r + 1, c) # 向下
dfs(r - 1, c) # 向上
dfs(r, c + 1) # 向右
dfs(r, c - 1) # 向左
# --- 主函数逻辑 ---
# 遍历网格中的每个单元格
for r in range(rows):
for c in range(cols):
# 如果是陆地 ('1'),说明发现了一个新岛屿
# 因为 DFS 会将访问过的 '1' 改为 '0',所以这里无需额外的 visited 检查
if grid[r][c] == '1':
# 发现新岛屿
island_count += 1
# 调用 DFS “淹没”此岛屿的所有部分
dfs(r, c)
# 注意:此方法修改了原始 grid。如果需要保留原始 grid,
# 应在开始时创建 grid 的副本进行操作。
return island_count