200. 岛屿数量

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
        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值