All*_* H. 1 graph cycle depth-first-search topological-sort
最近一直在练习图表题。
https://leetcode.com/problems/course-schedule-ii/
https://leetcode.com/problems/alien-dictionary/
我当前检测循环的方法是使用两个哈希集。一种用于访问节点,一种用于完全访问节点。然后我通过 DFS 遍历将结果推送到堆栈上。
如果我访问过当前位于访问集中的节点,那么这就是一个循环。
代码相当冗长,而且长度也很长。
谁能解释一下我如何使用更标准的顶排序算法(卡恩的)来检测循环并生成顶排序序列?
我只是想让我的方法退出或设置一些全局变量来标记已检测到循环。
非常感谢。
indegree[i]告诉我们节点 的入度i。q由所有这些入度为零的节点组成的队列。在 Khan 算法的任何一步,如果一个节点位于 q 中,则可以保证“学习这门课程是安全的”,因为它不依赖于任何“我们尚未学习的课程”。x:我们从队列中取出这些特殊的安全课程之一q,并从概念上将所有内容视为我们已从x图中删除了该节点及其所有传出边g。在实践中,我们不需要更新图g,对于 Khan 算法来说,只需更新in-degree其邻居的值以反映该节点不再存在就足够了。x,现在我们要更新其他课程依赖项以表明他们不再需要担心x。x的入度;x这可以引入更多入度为零的节点。在此步骤中,如果有更多节点的入度变为零,则将它们添加到q。我们重复步骤3来处理这些节点。每次我们从中删除一个节点时,q我们都会将其添加到最终的拓扑排序列表中result。result不会包含图中的所有节点,只会result返回部分节点。要检查是否存在环,只需检查 的长度是否result等于图中的节点数n。
q,因为总有一些其他前驱节点 x_(i-1) 具有从 x_(i-1) 到 xi 的边,从而阻止这种情况发生。Python 3 中Leetcode course-schedule-ii的完整解决方案:
from collections import defaultdict
def build_graph(edges, n):
g = defaultdict(list)
for i in range(n):
g[i] = []
for a, b in edges:
g[b].append(a)
return g
def topsort(g, n):
# -- Step 1 --
indeg = [0] * n
for u in g:
for v in g[u]:
indeg[v] += 1
# -- Step 2 --
q = []
for i in range(n):
if indeg[i] == 0:
q.append(i)
# -- Step 3 and 4 --
result = []
while q:
x = q.pop()
result.append(x)
for y in g[x]:
indeg[y] -= 1
if indeg[y] == 0:
q.append(y)
return result
def courses(n, edges):
g = build_graph(edges, n)
ordering = topsort(g, n)
# -- Step 5 --
has_cycle = len(ordering) < n
return [] if has_cycle else ordering
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2056 次 |
| 最近记录: |