LeetCode 417:太平洋大西洋水流问题——深度探索图论算法的魅力
2023-11-15 08:07:53
在计算机科学领域,图论算法扮演着举足轻重的角色,它让我们能够解决现实世界中错综复杂的互联问题。而 LeetCode 417:太平洋大西洋水流问题,正是图论算法魅力的完美展示。本文将带领你深入探索这道经典题目,了解其背后的算法思想和解题技巧。
引言
想象一座群山环绕的岛屿,太平洋在其东侧,大西洋在其西侧。雨水从天而降,汇聚成河流,奔流向海洋。我们想知道,哪些山顶的水最终将流入太平洋,哪些将流入大西洋。
问题
给你一个大小为 m x n
的整数矩阵 heights
,其中 heights[i][j]
表示第 i
行、第 j
列山峰的高度。如果下雨,水会从这些山顶流向较低的山顶。如果水流到边界,那么就会流入太平洋或大西洋。
返回一个布尔矩阵 pacificAtlantic
,其中 pacificAtlantic[i][j] = true
,表示水从第 i
行、第 j
列山顶可以流入太平洋和大西洋;false
则表示只能流入其中一者或都不流入。
算法思想
解决这个问题的关键在于识别哪些山顶可以流入太平洋和大西洋,而图论算法正是解决此类问题的利器。
深度优先搜索 (DFS)
DFS 是一种递归算法,它沿着一条路径深入探索图,直到到达终点或遇到死胡同。在本题中,我们可以使用 DFS 来追踪从每个山顶流出的水流路径。
从太平洋和 大西洋的边界山顶开始,分别执行两个 DFS 遍历:
- 太平洋遍历:从太平洋边界上的每个山顶出发,向四周较低的山顶递归搜索。
- 大西洋遍历:从大西洋边界上的每个山顶出发,向四周较低的山顶递归搜索。
通过两个 DFS 遍历,我们可以标记出哪些山顶可以流入太平洋或大西洋。
广度优先搜索 (BFS)
BFS 是一种基于队列的算法,它从起点开始逐层扩展搜索范围。在本题中,我们可以使用 BFS 来优化 DFS 的搜索过程。
从太平洋和大西洋的边界山顶开始,分别执行两个 BFS 队列:
- 太平洋队列:初始化队列,将太平洋边界上的山顶入队。
- 大西洋队列:初始化队列,将大西洋边界上的山顶入队。
循环遍历队列,依次取出山顶并将其四周较低的山顶入队。直到队列为空,表示所有可流入太平洋或大西洋的山顶都被遍历完毕。
代码实现
def pacificAtlantic(heights):
# 矩阵的行数和列数
m, n = len(heights), len(heights[0])
# 太平洋和 大西洋的可达矩阵,默认值为 False
pacific = [[False] * n for _ in range(m)]
atlantic = [[False] * n for _ in range(m)]
def dfs(i, j, visited, prev_height):
# 如果已经访问过或高度比之前访问的山顶低,则返回
if visited[i][j] or heights[i][j] < prev_height:
return
# 标记为已访问
visited[i][j] = True
# 递归搜索四周山顶
if i == 0 or j == 0: # 太平洋边界
pacific[i][j] = True
if i == m - 1 or j == n - 1: # 大西洋边界
atlantic[i][j] = True
if i > 0:
dfs(i - 1, j, visited, heights[i][j])
if i < m - 1:
dfs(i + 1, j, visited, heights[i][j])
if j > 0:
dfs(i, j - 1, visited, heights[i][j])
if j < n - 1:
dfs(i, j + 1, visited, heights[i][j])
# 从太平洋边界开始 DFS
for i in range(m):
dfs(i, 0, pacific, -1) # 左边界
for j in range(n):
dfs(0, j, pacific, -1) # 上边界
# 从大西洋边界开始 DFS
for i in range(m):
dfs(i, n - 1, atlantic, -1) # 右边界
for j in range(n):
dfs(m - 1, j, atlantic, -1) # 下边界
# 合并两个可达矩阵,得到最终结果
result = [[pacific[i][j] and atlantic[i][j] for j in range(n)] for i in range(m)]
return result
复杂度分析
- 时间复杂度:
O(mn)
,其中m
和n
分别是矩阵的行数和列数。DFS 或 BFS 遍历的复杂度为O(mn)
,合并两个矩阵的时间复杂度为O(mn)
。 - 空间复杂度:
O(mn)
,用于存储可达矩阵和队列。
结论
LeetCode 417:太平洋大西洋水流问题是一道经典的图论算法题目。通过 DFS 或 BFS 算法,我们可以识别出哪些山顶可以流入太平洋和大西洋。掌握这些算法技巧,将大大提升我们在解决实际问题中的能力。
希望这篇文章能帮助你更深入地理解图论算法,并激发你对计算机科学的热爱。让我们继续探索算法世界的奥秘,解决更多精彩的问题!