返回
LeetCode 28: 节点间通路 - 算法解密,从入门到精通
后端
2023-12-12 18:11:00
前言
在计算机科学领域,图论是一个至关重要的研究课题,它为解决现实世界中的许多问题提供了强大的工具。有向图是图论中的一个特殊类型,它由一系列节点和带有方向的边组成。在实际应用中,有向图被广泛用于表示各种关系,比如网络拓扑、社交网络和任务依赖关系。
LeetCode 28: 节点间通路 正是基于有向图的一道经典算法题目。它要求我们设计一个算法,在给定有向图的情况下,确定两个特定的节点之间是否存在通路。这道题对于理解有向图的性质和掌握图论算法至关重要。
深度优先搜索(DFS)
解决节点间通路 问题的一个常见方法是使用深度优先搜索(DFS)。DFS 是一种递归算法,它从图中的一个节点出发,并沿着路径深度搜索,直到到达目标节点或遍历完所有可能的路径。
DFS 算法步骤:
- 从起点节点开始,将其标记为已访问。
- 如果当前节点与目标节点相同,则返回 True 。
- 否则,遍历当前节点的所有未访问的相邻节点。
- 对于每个未访问的相邻节点,重复步骤 1-3。
- 如果所有相邻节点都已访问且未找到目标节点,则返回 False 。
DFS 代码示例:
def has_path_dfs(graph, source, destination):
# 标记起点节点为已访问
graph[source].visited = True
# 如果起点节点等于目标节点,则返回 True
if source == destination:
return True
# 遍历起点节点的所有未访问的相邻节点
for neighbor in graph[source].neighbors:
# 如果相邻节点未访问,则递归调用 has_path_dfs
if not neighbor.visited:
if has_path_dfs(graph, neighbor, destination):
return True
# 如果所有相邻节点都已访问且未找到目标节点,则返回 False
return False
拓扑排序
拓扑排序是另一种解决节点间通路 问题的算法。拓扑排序是一种用于有向无环图(DAG)的算法,它将图中的节点排列成一个线性序列,使得对于图中的任何边 (u, v)
,节点 u
在序列中都出现在节点 v
之前。
拓扑排序算法步骤:
- 初始化一个空队列。
- 对于图中的每个节点,如果其入度为 0,则将其入队。
- 只要队列不为空:
- 出队一个节点
u
。 - 对于
u
的每个相邻节点v
,将其入度减 1。 - 如果
v
的入度变为 0,则将其入队。
- 出队一个节点
- 如果拓扑排序成功完成,则说明图中不存在环。否则,图中存在环,拓扑排序无法完成。
拓扑排序代码示例:
def topological_sort(graph):
# 初始化入度表和队列
in_degrees = {}
queue = []
# 计算每个节点的入度
for node in graph.nodes:
in_degrees[node] = 0
# 将入度为 0 的节点入队
for node in graph.nodes:
if in_degrees[node] == 0:
queue.append(node)
# 进行拓扑排序
sorted_nodes = []
while queue:
# 出队一个节点
node = queue.pop(0)
sorted_nodes.append(node)
# 对于该节点的每个相邻节点,将其入度减 1
for neighbor in graph[node].neighbors:
in_degrees[neighbor] -= 1
# 如果相邻节点的入度变为 0,则将其入队
if in_degrees[neighbor] == 0:
queue.append(neighbor)
# 如果拓扑排序成功完成,则返回排序后的节点序列
return sorted_nodes
总结
节点间通路 问题是图论中一个经典的问题,它要求我们确定在给定有向图中两个特定节点之间是否存在通路。通过使用深度优先搜索或拓扑排序算法,我们可以高效地解决此问题。深度优先搜索适用于任意有向图,而拓扑排序仅适用于有向无环图。
掌握这些算法对于解决现实世界中的各种问题至关重要,例如网络路由、任务调度和依赖性管理。通过理解这些算法的原理和实现细节,你可以提升自己的算法技能,并为应对更复杂的算法挑战做好准备。