207. Course Schedule
# Problem:
There are a total of numCourses courses you have to take, labeled from 0 to numCourses - 1. You are given an array prerequisites where prerequisites[i] = [ai, bi] indicates that you must take course bi first if you want to take course ai.
- For example, the pair
[0, 1], indicates that to take course0you have to first take course1.
Return true if you can finish all courses. Otherwise, return false.
# Example 1:
Input: numCourses = 2, prerequisites = [[1,0]]
Output: true
Explanation: There are a total of 2 courses to take.
To take course 1 you should have finished course 0. So it is possible.
# Example 2:
Input: numCourses = 2, prerequisites = [[1,0],[0,1]]
Output: false
Explanation: There are a total of 2 courses to take.
To take course 1 you should have finished course 0, and to take course 0 you should also have finished course 1. So it is impossible.
# Constraints:
- 1 <= numCourses <= 105
- 0 <= prerequisites.length <= 5000
- prerequisites[i].length == 2
- 0 <= ai, bi < numCourses
- All the pairs prerequisites[i] are unique.
# Solution:
Topological sorting of directed graphs. The purpose of topological sorting is to check whether it can be completed or not. If there are no loops, all the prerequisites and non-prerequisites can be completed. First, convert the course into a 2D graph, and then build a visted array to record the visited and the visiting. There are three states in total.
- Haven't visited yet (0)
- Visiting (1)
- Visited (2)
If the node we step on is already visiting, we are back to ourselves when exploring its neighbors. Therefore, it means we have a loop.
If you go to the one we have already visited, it means we can finish the route, and there is no loop. If there is any loop detected during the DFS, return true.
It's similar to post-order traversal, first set as visiting, then explore neighbors, enter dfs recursively, and mark as visited after returning
Time complexity:
Space complexity:
# Python
class Solution:
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
graph = [[] for _ in range(numCourses)]
for first, second in prerequisites:
graph[first].append(second)
# 0 = unknown # 1 = visiting # 2 = visited
visit = [0] * numCourses
def dfs(curr, visit):
if visit[curr] == 1: return True
if visit[curr] == 2: return False
visit[curr] = 1
for j in graph[curr]:
if dfs(j, visit): return True
visit[curr] = 2
return False
for i in range(numCourses) :
if dfs(i, visit): return False
return True
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Java
class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
ArrayList<Integer>[] graph = new ArrayList[numCourses];
for(int i = 0; i < numCourses; i ++) graph[i] = new ArrayList<>();
for(int[] course: prerequisites){
graph[course[0]].add(course[1]);
}
int[] visited = new int[numCourses];
for(int i = 0; i < numCourses; i ++){
if(dfs(graph, visited, i)) return false;
}
return true;
}
private boolean dfs(ArrayList<Integer>[] graph, int[] visited, int curr){
if(visited[curr] == 1) return true;
if(visited[curr] == 2) return false;
visited[curr] = 1;
for(Integer neighbor : graph[curr]){
if(dfs(graph, visited, neighbor)) return true;
}
visited[curr] = 2;
return false;
}
}
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