207. Course Schedule
Medium
There are a total of numCourses
courses you have to take, labeled from 0
to numCourses-1
.
Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]
Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?
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:
- The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented.
- You may assume that there are no duplicate edges in the input prerequisites.
1 <= numCourses <= 10^5
笔记:
方法1:DFS
遍历每一个course,一直到树的根部,如果visited==0表示还没有访问过,visited==1表示正在访问,继续往下的时候发现有个节点visited==1说明出现了环,visited==2 表示这个节点已经访问过了,如果这条路径不是环的话,那么visited==2的节点及以下节点全部都是合法的,不存在环,下一次如果有个节点访问到了visited==2的节点就停止,不继续往下走了,因为这个点下面都是合法的了,不需要再深搜了。当遍历完所有的course,没有发现环的话,结果最后是True
class Solution:
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
courses = collections.defaultdict([])
for pre, post in prerequisites:
courses[pre].append(post)
visited = [0] * numCourses
def dfs(course):
if visited[course] == 1:
return False
if visited[course] == 2:
return True
visited[course] = 1
for i in courses[course]:
if not dfs(i):
return False
visited[course] = 2
return True
for course_num in range(numCourses):
if not dfs(course_num):
return False
return True
方法2:BFS
BFS是一层一层的遍历。思路是每个节点都有它的入度,有两个前置课程,则入度为2. 我们每次都选择入度为0的那些点作为一层的节点,每当这个节点访问完了,该节点的子节点入度减一,如果减一后它的入度为0,则压入到queue里面。在遍历每一层的节点的时候,统计盖层节点的个数,如果最后节点的个数与numCourse一样,则说明不存在环,如果cnt的个数少于numCourse,则说明存在环。
这两种方法其实都是创建了一棵树,然后用不同的方法判断该树中是否有环。
import collections
class Solution:
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
courses = collections.defaultdict(list)
queue = collections.deque()
in_degree = [0] * numCourses
cnt = 0
for pre, post in prerequisites:
in_degree[post] += 1
courses[pre].append(post)
for i in range(numCourses):
if in_degree[i] == 0:
queue.append(i)
while queue:
front = queue.popleft()
cnt += 1
for i in courses[front]:
in_degree[i] -= 1
if in_degree == 0:
queue.append(i)
return cnt == numCourses