Solution 1
from collections import defaultdict
class Solution:
WHITE = 1
GRAY = 2
BLACK = 3
def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:
topological_sorted_order = []
adj_list = defaultdict(list)
for des, src in prerequisites:
adj_list[src].append(des)
is_possible = True
color = {k: Solution.WHITE for k in range(numCourses)}
def dfs(node):
nonlocal is_possible
if not is_possible:
return
color[node] = Solution.GRAY
if node in adj_list:
for neighbor in adj_list[node]:
if color[neighbor] == Solution.WHITE:
dfs(neighbor)
elif color[neighbor] == Solution.GRAY:
is_possible = False
color[node] = Solution.BLACK
topological_sorted_order.append(node)
for course in range(numCourses):
if color[course] == Solution.WHITE:
dfs(course)
return topological_sorted_order[::-1] if is_possible else []
Time O(n). Space O(n).
Solution 2
from collections import defaultdict
class Solution:
def findOrder(self, numCourses, prerequisites):
"""
:type numCourses: int
:type prerequisites: List[List[int]]
:rtype: List[int]
"""
# Prepare the graph
adj_list = defaultdict(list)
indegree = {}
for dest, src in prerequisites:
adj_list[src].append(dest)
# Record each node's in-degree
indegree[dest] = indegree.get(dest, 0) + 1
# Queue for maintainig list of nodes that have 0 in-degree
zero_indegree_queue = [k for k in range(numCourses) if k not in indegree]
topological_sorted_order = []
# Until there are nodes in the Q
while zero_indegree_queue:
# Pop one node with 0 in-degree
vertex = zero_indegree_queue.pop(0)
topological_sorted_order.append(vertex)
# Reduce in-degree for all the neighbors
if vertex in adj_list:
for neighbor in adj_list[vertex]:
indegree[neighbor] -= 1
# Add neighbor to Q if in-degree becomes 0
if indegree[neighbor] == 0:
zero_indegree_queue.append(neighbor)
return topological_sorted_order if len(topological_sorted_order) == numCourses else []
Time O(n). Space O(n).