You are given an integer n, which indicates that there are n courses labeled from 1 to n. You are also given an array relations where relations[i] = [prevCourseᵢ, nextCourseᵢ], representing a prerequisite relationship between course prevCourseᵢ and course nextCourseᵢ: course prevCourseᵢ has to be taken before course nextCourseᵢ.
In one semester, you can take any number of courses as long as you have taken all the prerequisites in the previous semester for the courses you are taking.
Return the minimum number of semesters needed to take all courses. If there is no way to take all the courses, return -1.
Example 1:
Input: n = 3, relations = [[1,3],[2,3]]
Output: 2Explanation: The figure above represents the given graph.
In the first semester, you can take courses 1 and 2.
In the second semester, you can take course 3.
Example 2:
Input: n = 3, relations = [[1,2],[2,3],[3,1]]
Output: -1Explanation: No course can be studied because they are prerequisites of each other.
Constraints:
1 <= n <= 50001 <= relations.length <= 5000relations[i].length == 21 <= prevCourseᵢ, nextCourseᵢ <= nprevCourseᵢ != nextCourseᵢ[prevCourseᵢ, nextCourseᵢ] are unique.class Solution:
def minimumSemesters(self, N: int, relations: List[List[int]]) -> int:
graph = {i: [] for i in range(1, N + 1)}
in_count = {i: 0 for i in range(1, N + 1)} # or in-degree
for start_node, end_node in relations:
graph[start_node].append(end_node)
in_count[end_node] += 1
queue = []
# we use list here since we are not
# popping from the front in this code
for node in graph:
if in_count[node] == 0:
queue.append(node)
step = 0
studied_count = 0
# start learning with BFS
while queue:
# start new semester
step += 1
next_queue = []
for node in queue:
studied_count += 1
end_nodes = graph[node]
for end_node in end_nodes:
in_count[end_node] -= 1
# if all prerequisite courses learned
if in_count[end_node] == 0:
next_queue.append(end_node)
queue = next_queue
return step if studied_count == N else -1Where is the length of
relationsand is the number of courses.
class Solution:
def minimumSemesters(self, N: int, relations: List[List[int]]) -> int:
graph = {i: [] for i in range(1, N + 1)}
for start_node, end_node in relations:
graph[start_node].append(end_node)
# check if the graph contains a cycle
visited = {}
def dfs_check_cycle(node: int) -> bool:
# return True if graph has a cycle
if node in visited:
return visited[node]
else:
# mark as visiting
visited[node] = -1
for end_node in graph[node]:
if dfs_check_cycle(end_node):
# we meet a cycle!
return True
# mark as visited
visited[node] = False
return False
# if has cycle, return -1
for node in graph.keys():
if dfs_check_cycle(node):
return -1
# if no cycle, return the longest path
visited_length = {}
def dfs_max_path(node: int) -> int:
# return the longest path (inclusive)
if node in visited_length:
return visited_length[node]
max_length = 1
for end_node in graph[node]:
length = dfs_max_path(end_node)
max_length = max(length+1, max_length)
# store it
visited_length[node] = max_length
return max_length
return max(dfs_max_path(node)for node in graph.keys())Where is the length of
relationsand is the number of courses.
class Solution:
def minimumSemesters(self, N: int, relations: List[List[int]]) -> int:
graph = {i: [] for i in range(1, N + 1)}
for start_node, end_node in relations:
graph[start_node].append(end_node)
visited = {}
def dfs(node: int) -> int:
# return the longest path (inclusive)
if node in visited:
return visited[node]
else:
# mark as visiting
visited[node] = -1
max_length = 1
for end_node in graph[node]:
length = dfs(end_node)
# we meet a cycle!
if length == -1:
return -1
else:
max_length = max(length+1, max_length)
# mark as visited
visited[node] = max_length
return max_length
max_length = -1
for node in graph.keys():
length = dfs(node)
# we meet a cycle!
if length == -1:
return -1
else:
max_length = max(length, max_length)
return max_lengthWhere is the length of
relationsand is the number of courses.