Course Schedule II
You are given an array prerequisites where prerequisites[i] = [a, b] indicates that you must take course b first if you want to take course a.
For example, the pair [0, 1], indicates that to take course 0 you have to first take course 1.
There are a total of numCourses courses you are required to take, labeled from 0 to numCourses - 1.
Return a valid ordering of courses you can take to finish all courses. If there are many valid answers, return any of them. If it’s not possible to finish all courses, return an empty array.
Example 1:
Input: numCourses = 3, prerequisites = [[1,0]]
Output: [0,1,2]
Explanation: We must ensure that course 0 is taken before course 1.
Example 2:
Input: numCourses = 3, prerequisites = [[0,1],[1,2],[2,0]]
Output: []
Explanation: It’s impossible to finish all courses.
Constraints:
1 <= numCourses <= 1000
0 <= prerequisites.length <= 1000
All prerequisite pairs are unique.
Solution
It is a classic Topological Sorting problem, the official gives a solution based on DFS. Here, I will give the solution based on Kahn’s algorithm.
All we need to do is to maintain a set of nodes that each one of them is zero in-degree, which means they have no prerequisites, or the prerequisites are met. Each time we pick up a node from this set, adding it to the answer list, and we go through every edge comes from this node, reducing the in-degree of the next node by 1. During this process, we keep adding nodes that in-degree is reduced to 0 until the zero in-degree node set becoming empty.
If the length of answer list is equal to the number of nodes, it is solvable, or we shall return a empty list.
Code
class Solution:
def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:
prereq_map = {}
zero_in_degree = []
in_degree_cnt = {i: 0 for i in range(numCourses)}
for prereq in prerequisites:
if prereq[1] in prereq_map:
prereq_map[prereq[1]].append(prereq[0])
else:
prereq_map[prereq[1]] = [prereq[0]]
in_degree_cnt[prereq[0]] = in_degree_cnt[prereq[0]] + 1
for key, value in in_degree_cnt.items():
if value == 0:
zero_in_degree.append(key)
answer = []
while len(zero_in_degree) > 0:
current_node = zero_in_degree.pop()
answer.append(current_node)
for nxt_node in prereq_map.get(current_node, []):
in_degree_cnt[nxt_node] -= 1
if in_degree_cnt[nxt_node] == 0:
zero_in_degree.append(nxt_node)
if len(answer) != len(in_degree_cnt):
return []
return answer