-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSolution.py
119 lines (95 loc) · 3.27 KB
/
Solution.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import collections
from typing import List
class Solution:
def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:
return self.findOrderBfs(numCourses, prerequisites)
def findOrderDfs(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:
# 存储有向图
edges = collections.defaultdict(list)
# 标记每个节点的状态:0=未搜索 1=搜索中 2=已完成
visited = [0] * numCourses
# 用数组来模拟栈,下标0为栈底,n-1为栈顶
result = list()
# 判断有向图中是否有环
valid = True
for info in prerequisites:
edges[info[1]].append(info[0])
def dfs(u: int):
nonlocal valid
# 将节点标记为「搜索中」
visited[u] = 1
# 搜索其相邻节点
# 只要发现有环,立刻停止搜索
for v in edges[u]:
# 如果「未搜索」那么搜索相邻节点
if visited[v] == 0:
dfs(v)
if not valid:
return
# 如果「搜索中」说明找到了环
elif visited[v] == 1:
valid = False
return
# 将节点标记为「已完成」
visited[u] = 2
# 将节点入栈
result.append(u)
# 每次挑选一个「未搜索」的节点,开始进行深度优先搜索
for i in range(numCourses):
if valid and not visited[i]:
dfs(i)
if not valid:
return list()
# 如果没有环,那么就有拓扑排序
# 注意下标 0 为栈底,因此需要将数组反序输出
return result[::-1]
def findOrderBfs(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:
# 存储有向图
edges = collections.defaultdict(list)
# 存储每个节点的入度
indeg = [0] * numCourses
# 存储答案
result = list()
for info in prerequisites:
edges[info[1]].append(info[0])
indeg[info[0]] += 1
# 将所有入度为 0 的节点放入队列中
q = collections.deque([u for u in range(numCourses) if indeg[u] == 0])
while q:
# 从队首取出一个节点
u = q.popleft()
# 放入答案
result.append(u)
for v in edges[u]:
indeg[v] -= 1
# 如果相邻节点 v 的入度为 0,就可以选 v 对应的课程了
if indeg[v] == 0:
q.append(v)
if len(result) != numCourses:
result = list()
return result
def test1():
solution = Solution()
num = 2
l = [[1, 0]]
ll = solution.findOrder(num, l)
print(ll)
assert(ll == [0, 1])
def test2():
solution = Solution()
num = 4
l = [[1, 0], [2, 0], [3, 1], [3, 2]]
ll = solution.findOrder(num, l)
print(ll)
assert(ll in [[0, 1, 2, 3], [0, 2, 1, 3]])
def test3():
solution = Solution()
num = 1
l = []
ll = solution.findOrder(num, l)
print(ll)
assert(ll == [0])
if __name__ == '__main__':
test1()
test2()
test3()