309.魔幻世界中的安全区计算 | 豆包MarsCode AI 刷题

5 阅读3分钟

问题描述

小F被神秘力量带入了一个魔幻世界,这里危机四伏。为了在异世界中生存,小F需要找到安全区。异世界可以被表示为一个大小为 n x m 的二维数组,每个格子的值代表该位置的危险程度。

小F的能力值为 X,当某个格子的危险程度小于等于 X 时,这个格子是安全的。如果多个安全的格子相邻(上下左右连通),它们可以构成一个安全区。你需要帮助小F计算出一共有多少个安全区。

问题理解

需要在一个 n x m 的二维数组中找到所有安全区的数量。安全区的定义是:所有相邻的格子(上下左右)的危险程度都小于等于 X

数据结构选择

  1. 二维数组:用于存储每个格子的危险程度。
  2. 访问标记数组:用于标记哪些格子已经被访问过,避免重复计算。

算法步骤

  1. 初始化:创建一个与输入数组相同大小的访问标记数组,初始值为 False,表示所有格子都未被访问。
  2. 遍历数组:对于每个格子,如果该格子未被访问且危险程度小于等于 X,则从这个格子开始进行深度优先搜索(DFS)或广度优先搜索(BFS),找到所有与之相邻的安全格子,并将它们标记为已访问。
  3. 计数:每完成一次搜索,安全区的数量加一。
  4. 返回结果:遍历结束后,返回安全区的数量。

具体步骤

  1. DFS/BFS函数:编写一个递归的DFS函数或使用队列的BFS函数,用于从某个未访问的安全格子开始,访问所有与之相邻的安全格子。
  2. 主函数:遍历整个二维数组,调用DFS/BFS函数,并统计安全区的数量。

代码实现

def solution(n: int, m: int, X: int, a: list[list[int]]) -> int:
    visited = [[False] * m for _ in range(n)]

    def dfs(i, j):
        if i < 0 or i >= n or j < 0 or j >= m or visited[i][j] or a[i][j] > X:
            return
        visited[i][j] = True
        dfs(i + 1, j)  # 下
        dfs(i - 1, j)  # 上
        dfs(i, j + 1)  # 右
        dfs(i, j - 1)  # 左

    safe_zones = 0

    for i in range(n):
        for j in range(m):
            if not visited[i][j] and a[i][j] <= X:
                dfs(i, j)
                safe_zones += 1

    return safe_zones
    

时间复杂度

  1. 遍历二维数组:在主函数中,我们遍历了整个 n x m 的二维数组。这一步的时间复杂度是 O(n * m)
  2. DFS函数调用:对于每个未访问且危险程度小于等于 X 的格子,我们调用一次DFS函数。在最坏情况下,每个格子都会被访问一次,因此DFS函数的时间复杂度也是 O(n * m)

综合来看,整个算法的时间复杂度是 O(n * m)

空间复杂度

  1. 访问标记数组:我们创建了一个与输入数组相同大小的访问标记数组 visited,其空间复杂度是 O(n * m)
  2. 递归栈空间:在DFS函数中,递归调用会占用栈空间。在最坏情况下,递归深度可以达到 n * m,因此递归栈的空间复杂度也是 O(n * m)

综合来看,整个算法的空间复杂度是 O(n * m)

总结

  • 时间复杂度O(n * m)
  • 空间复杂度O(n * m)