Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit a13d3c6

Browse files
committed
started working on graph algorithms
1 parent 5069c8f commit a13d3c6

File tree

3 files changed

+217
-0
lines changed

3 files changed

+217
-0
lines changed

‎README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
- [二分搜索](./basic_algorithm/binary_search.md)
3535
- [排序算法](./basic_algorithm/sort.md)
3636
- [动态规划](./basic_algorithm/dp.md)
37+
- [图相关算法](./basic_algorithm/graph/)
3738

3839
### 算法思维 🦁
3940

‎basic_algorithm/graph/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
### 图相关算法
2+
3+
Ongoing...
4+
5+
[拓扑排序](./topological_sorting.md)
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
# 拓扑排序
2+
3+
图的拓扑排序 (topological sorting) 一般用于给定一系列偏序关系,求一个全序关系的题目中。以元素为结点,以偏序关系为边构造有向图,然后应用拓扑排序算法即可得到全序关系。
4+
5+
### [course-schedule-ii](https://leetcode-cn.com/problems/course-schedule-ii/)
6+
7+
> 给定课程的先修关系,求一个可行的修课顺序
8+
9+
**图森面试真题**。非常经典的拓扑排序应用题目。下面给出 3 种实现方法,可以当做模板使用。
10+
11+
12+
13+
方法 1:DFS 的递归实现
14+
15+
```Python
16+
NOT_VISITED = 0
17+
DISCOVERING = 1
18+
VISITED = 2
19+
20+
class Solution:
21+
def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:
22+
23+
# construct graph
24+
graph_neighbor = collections.defaultdict(list)
25+
for course, pre in prerequisites:
26+
graph_neighbor[pre].append(course)
27+
28+
# recursive postorder DFS for topological sort
29+
tsort_rev = []
30+
status = [NOT_VISITED] * numCourses
31+
32+
def dfs(course):
33+
status[course] = DISCOVERING
34+
for n in graph_neighbor[course]:
35+
if status[n] == DISCOVERING or (status[n] == NOT_VISITED and not dfs(n)):
36+
return False
37+
tsort_rev.append(course)
38+
status[course] = VISITED
39+
return True
40+
41+
for course in range(numCourses):
42+
if status[course] == NOT_VISITED and not dfs(course):
43+
return []
44+
45+
return tsort_rev[::-1]
46+
```
47+
48+
方法 2:DFS 的迭代实现
49+
50+
```Python
51+
NOT_VISITED = 0
52+
DISCOVERING = 1
53+
VISITED = 2
54+
55+
class Solution:
56+
def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:
57+
58+
# construct graph
59+
graph_neighbor = collections.defaultdict(list)
60+
for course, pre in prerequisites:
61+
graph_neighbor[pre].append(course)
62+
63+
# iterative postorder DFS for topological sort
64+
tsort_rev = []
65+
status = [NOT_VISITED] * numCourses
66+
67+
dfs = []
68+
for course in range(numCourses):
69+
if status[course] == NOT_VISITED:
70+
dfs.append(course)
71+
status[course] = DISCOVERING
72+
73+
while dfs:
74+
if graph_neighbor[dfs[-1]]:
75+
n = graph_neighbor[dfs[-1]].pop()
76+
if status[n] == DISCOVERING:
77+
return []
78+
if status[n] == NOT_VISITED:
79+
dfs.append(n)
80+
status[n] = DISCOVERING
81+
else:
82+
tsort_rev.append(dfs.pop())
83+
status[tsort_rev[-1]] = VISITED
84+
85+
return tsort_rev[::-1]
86+
```
87+
88+
方法 3:[Kahn's algorithm](https://en.wikipedia.org/wiki/Topological_sorting#Kahn's_algorithm)
89+
90+
```Python
91+
class Solution:
92+
def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:
93+
94+
# construct graph with indegree data
95+
graph_neighbor = collections.defaultdict(list)
96+
indegree = collections.defaultdict(int)
97+
98+
for course, pre in prerequisites:
99+
graph_neighbor[pre].append(course)
100+
indegree[course] += 1
101+
102+
# Kahn's algorithm
103+
src_cache = [] # can also use queue
104+
for i in range(numCourses):
105+
if indegree[i] == 0:
106+
src_cache.append(i)
107+
108+
tsort = []
109+
while src_cache:
110+
tsort.append(src_cache.pop())
111+
for n in graph_neighbor[tsort[-1]]:
112+
indegree[n] -= 1
113+
if indegree[n] == 0:
114+
src_cache.append(n)
115+
116+
return tsort if len(tsort) == numCourses else []
117+
```
118+
119+
### [alien-dictionary](https://leetcode-cn.com/problems/alien-dictionary/)
120+
121+
```Python
122+
class Solution:
123+
def alienOrder(self, words: List[str]) -> str:
124+
125+
N = len(words)
126+
127+
if N == 0:
128+
return ''
129+
130+
if N == 1:
131+
return words[0]
132+
133+
# construct graph
134+
indegree = {c: 0 for word in words for c in word}
135+
graph = collections.defaultdict(list)
136+
137+
for i in range(N - 1):
138+
first, second = words[i], words[i + 1]
139+
len_f, len_s = len(first), len(second)
140+
find_different = False
141+
for j in range(min(len_f, len_s)):
142+
f, s = first[j], second[j]
143+
if f != s:
144+
if s not in graph[f]:
145+
graph[f].append(s)
146+
indegree[s] += 1
147+
find_different = True
148+
break
149+
150+
if not find_different and len_f > len_s:
151+
return ''
152+
153+
tsort = []
154+
src_cache = [c for c in indegree if indegree[c] == 0]
155+
156+
while src_cache:
157+
tsort.append(src_cache.pop())
158+
for n in graph[tsort[-1]]:
159+
indegree[n] -= 1
160+
if indegree[n] == 0:
161+
src_cache.append(n)
162+
163+
return ''.join(tsort) if len(tsort) == len(indegree) else ''
164+
```
165+
166+
### [sequence-reconstruction](https://leetcode-cn.com/problems/sequence-reconstruction/)
167+
168+
Kahn's algorithm 可以判断拓扑排序是否唯一。
169+
170+
```Python
171+
class Solution:
172+
def sequenceReconstruction(self, org: List[int], seqs: List[List[int]]) -> bool:
173+
174+
N = len(org)
175+
inGraph = [False] * (N + 1)
176+
graph_set = collections.defaultdict(set)
177+
for seq in seqs:
178+
if seq:
179+
if seq[0] > N or seq[0] < 1:
180+
return False
181+
inGraph[seq[0]] = True
182+
for i in range(1, len(seq)):
183+
if seq[i] > N or seq[i] < 1:
184+
return False
185+
inGraph[seq[i]] = True
186+
graph_set[seq[i - 1]].add(seq[i])
187+
188+
indegree = collections.defaultdict(int)
189+
for node in graph_set:
190+
for n in graph_set[node]:
191+
indegree[n] += 1
192+
193+
num_valid, count0, src = 0, -1, 0
194+
for i in range(1, N + 1):
195+
if inGraph[i] and indegree[i] == 0:
196+
count0 += 1
197+
src = i
198+
199+
i = 0
200+
while count0 == i and src == org[i]:
201+
num_valid += 1
202+
for n in graph_set[src]:
203+
indegree[n] -= 1
204+
if indegree[n] == 0:
205+
count0 += 1
206+
src = n
207+
i += 1
208+
209+
return num_valid == N
210+
```
211+

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /