返回

LeetCode 28: 节点间通路 - 算法解密,从入门到精通

后端

前言

在计算机科学领域,图论是一个至关重要的研究课题,它为解决现实世界中的许多问题提供了强大的工具。有向图是图论中的一个特殊类型,它由一系列节点和带有方向的边组成。在实际应用中,有向图被广泛用于表示各种关系,比如网络拓扑、社交网络和任务依赖关系。

LeetCode 28: 节点间通路 正是基于有向图的一道经典算法题目。它要求我们设计一个算法,在给定有向图的情况下,确定两个特定的节点之间是否存在通路。这道题对于理解有向图的性质和掌握图论算法至关重要。

深度优先搜索(DFS)

解决节点间通路 问题的一个常见方法是使用深度优先搜索(DFS)。DFS 是一种递归算法,它从图中的一个节点出发,并沿着路径深度搜索,直到到达目标节点或遍历完所有可能的路径。

DFS 算法步骤:

  1. 从起点节点开始,将其标记为已访问。
  2. 如果当前节点与目标节点相同,则返回 True
  3. 否则,遍历当前节点的所有未访问的相邻节点。
  4. 对于每个未访问的相邻节点,重复步骤 1-3。
  5. 如果所有相邻节点都已访问且未找到目标节点,则返回 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 之前。

拓扑排序算法步骤:

  1. 初始化一个空队列。
  2. 对于图中的每个节点,如果其入度为 0,则将其入队。
  3. 只要队列不为空:
    • 出队一个节点 u
    • 对于 u 的每个相邻节点 v,将其入度减 1。
    • 如果 v 的入度变为 0,则将其入队。
  4. 如果拓扑排序成功完成,则说明图中不存在环。否则,图中存在环,拓扑排序无法完成。

拓扑排序代码示例:

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

总结

节点间通路 问题是图论中一个经典的问题,它要求我们确定在给定有向图中两个特定节点之间是否存在通路。通过使用深度优先搜索或拓扑排序算法,我们可以高效地解决此问题。深度优先搜索适用于任意有向图,而拓扑排序仅适用于有向无环图。

掌握这些算法对于解决现实世界中的各种问题至关重要,例如网络路由、任务调度和依赖性管理。通过理解这些算法的原理和实现细节,你可以提升自己的算法技能,并为应对更复杂的算法挑战做好准备。