不同岛屿的数量

694 不同岛屿的数量
这道题要给出不同岛屿的数量,最直观的想法就是对发现的不同岛屿进行序列化,然后把序列化结果存到HashSet,那怎么序列化呢?
其实比较类似于二叉树的序列化,记录遍历顺序(方向),这里用
⽤ 1, 2, 3, 4 代表上下左右,⽤ -1, -2, -3, -4 代表上下左右的撤销,前序后续位置分别增加遍历顺序,即可实现序列化。

关于岛屿的相似题目:

  1. 岛屿数量 – 二维矩阵的dfs算法
  2. 封闭岛屿数量 – 二维矩阵的dfs算法
  3. 统计封闭岛屿的数目
  4. 统计子岛屿
  5. 不同岛屿的数量
  6. 岛屿的周长

class NumDistinctIslands:
    """
    694 不同岛屿的数量
    https://leetcode.cn/problems/number-of-distinct-islands/
    """
    def solution(self, grid):
        islands = set()
        m, n = len(grid), len(grid[0])

        # 遍历grid,就是所有的封闭岛屿
        for i in range(m):
            for j in range(n):
                # 淹掉这个岛屿,同时存储岛屿的序列化结果
                if grid[i][j] == 1:
                    self.sb = ''
                    # 初始的⽅向可以随便写,不影响正确性
                    dir = 666
                    self.dfs_matrix(grid, i, j, dir)
                    islands.add(self.sb)
        return len(islands)

    def dfs_matrix(self, grid, i, j, dir):
        m, n = len(grid), len(grid[0])

        # 跳出递归条件
        if i < 0 or i >= m or j < 0 or j >= n:
            return

        if grid[i][j] == 0:
            return

        # 前序序遍历位置:进入(i, j)
        grid[i][j] = 0
        self.sb += str(dir) + ','

        self.dfs_matrix(grid, i - 1, j, 1)  # 上
        self.dfs_matrix(grid, i + 1, j, 2)  # 下
        self.dfs_matrix(grid, i, j - 1, 3)  # 左
        self.dfs_matrix(grid, i, j + 1, 4)  # 右

        # 后序遍历位置:离开 (i, j)
        self.sb += str(-dir) + ','


<think>好的,我现在需要帮助用户了解如何用Python实现计算岛屿数量的算法。首先,我得回忆一下这个问题。题目是说,给定一个二维网格,其中'1'代表陆地,'0'代表水域,相邻的陆地(上下左右)组成一个岛屿,要求统计岛屿数量。用户提供的引用资料里提到了一些方法,比如递归、迭代、双向队列、并查集等。我需要把这些方法中的主要思路整理出来,并给出代码示例。 首先,我得确定基本思路。通常,这类问题可以通过深度优先搜索(DFS)或广度优先搜索(BFS)来解决。用户提到的引用中也提到了递归(DFS)和迭代(BFS)的方法。并查集可能稍微复杂一些,但也是一个有效的方法。不过对于初学者来说,DFS和BFS可能更容易理解。 我应该从最简单的递归方法开始。递归DFS的思路是遍历整个网格,当遇到一个'1'时,就启动DFS,将所有相邻的'1'都标记为已访问,通常是通过修改为'0'来避免重复计算。这样,每次遇到一个新的'1',岛屿数量就加一,然后递归处理周围四个方向。 然后,可能需要考虑迭代的方法,比如用队列实现的BFS。这里同样需要遍历网格,遇到'1'时,启动BFS,将周围的'1'加入队列,并逐个处理,直到队列为空。这样也能标记整个岛屿。 另外,用户提供的引用里提到了高速双向队列,可能是指使用collections.deque来提高效率,这一点可以在BFS部分提到。并查集的方法可能稍微复杂,需要处理每个节点的父节点,合并相邻的陆地,最后统计根节点的数量。不过对于一般情况,DFS和BFS已经足够。 接下来,我需要确保代码示例的正确性。比如递归的DFS函数需要处理边界条件,比如索引是否超出范围,当前节点是否为'1'。同时,要修改访问过的节点,防止重复计算。BFS的示例同样需要注意这些,同时使用队列来存储待处理的节点。 另外,用户可能关心时间复杂度和空间复杂度。这个问题的时间复杂度通常是O(M*N),因为每个节点最多被访问一次。空间复杂度对于DFS来说,最坏情况下是O(M*N)(比如整个网格都是陆地,递归栈的深度),而BFS的空间复杂度取决于队列的大小,可能也是O(min(M,N)),但具体可能需要更详细的分析。 在编写步骤的时候,应该分点说明,比如遍历网格、发现陆地、标记已访问、统计数量等。代码部分需要符合Python语法,使用正确的缩进和结构。同时,需要解释每个步骤的作用,比如双层循环的作用,递归或迭代的处理方式。 可能还需要比较不同方法的优缺点。比如递归的DFS代码简洁,但可能有栈溢出的风险;而BFS使用队列,适合较大的网格。并查集可能在处理动态连接问题时更高效,但实现起来稍微复杂。 最后,生成的相关问题需要考虑用户可能进一步想知道的内容,比如如何优化算法,处理大规模数据,或者不同方法的性能比较等。 总结一下,我需要整理出DFS和BFS两种方法的实现步骤,给出代码示例,并简要分析复杂度。同时,比较不同方法的适用场景,确保用户能够理解并选择合适的方法。</think>### 逐步解释:Python实现计算岛屿数量 #### 1. **问题理解** 岛屿数量问题要求在二维网格中统计由相邻陆地('1')组成的独立区域数量,相邻指水平或垂直方向相连[^3][^4]。 #### 2. **核心思路** 通过遍历网格中的每个点: - 遇到陆地('1')时启动**深度优先搜索(DFS)**或**广度优先搜索(BFS)**,将所有相连的陆地标记为已访问。 - 每启动一次搜索,岛屿数量+1。 #### 3. **DFS递归实现** ```python def num_islands_dfs(grid): if not grid: return 0 rows, cols = len(grid), len(grid[0]) count = 0 def dfs(i, j): if i < 0 or j < 0 or i >= rows or j >= cols or 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(rows): for j in range(cols): if grid[i][j] == '1': dfs(i, j) count += 1 return count ``` **步骤说明**: 1. 遍历每个网格点。 2. 遇到未访问的陆地时,递归标记所有相连陆地为'0'。 3. 统计启动搜索的次数即为岛屿数量[^5]。 #### 4. **BFS迭代实现** ```python from collections import deque def num_islands_bfs(grid): if not grid: return 0 rows, cols = len(grid), len(grid[0]) count = 0 for i in range(rows): for j in range(cols): if grid[i][j] == '1': queue = deque([(i, j)]) grid[i][j] = '0' # 标记起点 while queue: x, y = queue.popleft() for dx, dy in [(-1,0), (1,0), (0,-1), (0,1)]: nx, ny = x + dx, y + dy if 0 <= nx < rows and 0 <= ny < cols and grid[nx][ny] == '1': grid[nx][ny] = '0' queue.append((nx, ny)) count += 1 return count ``` **特点**: - 使用队列实现层级遍历。 - 避免递归栈溢出风险,适合大规模网格[^2]。 #### 5. **复杂度分析** - **时间复杂度**:$$O(M \times N)$$(每个节点仅访问一次)。 - **空间复杂度**: - DFS:$$O(M \times N)$$(递归栈深度)。 - BFS:$$O(\min(M, N))$$(队列最大长度)[^5]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NLP_wendi

谢谢您的支持。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值