题目描述
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?
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
例子
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.
解释
有一个课表prerequisites,里面是一个[i, j]的键值对,表示要上i这门课,必须先上j这门课。还有一个正整数numCourses,表示总共有多少门课。我们现在要求有没有一种上课的方法,让一个人能够上完所有的课。
思路 拓扑排序 BFS
如果我们把prerequisites这个列表想成一个有向图,则能够上完所有课的条件就是图中无环,即该图能够拓扑排序。因此这是一道典型的广度优先搜索(BFS)的应用。
首先我们构造有向图。我们让有向图的边从j指向i。构造图的方法不多赘述了,python中用字典很容易实现。
然后我们创建一个数组,数组中存储每一门课程当前条件下还需要多少个直接的prerequisites。即每个课程在有向图中的对应点的入度是多少。这个变量很关键。我们在后面BFS的过程中判断是否入队列就是依照这个数组里面的值。
最后我们维护一个队列。队列中放所有入度为0的点。具体实现中,我们首先把初始入度就为0的点放进去,然后对这些点在字典中去查找对应的value,把value对应的在数组中的值减1,如果此时值变为0,则放入队列。
同时我们用一个变量total来记录当前总共上了几门课。如果最后total的值和numCourses相等,则返回True。
代码
class Solution(object):
def canFinish(self, numCourses, prerequisites):
"""
:type numCourses: int
:type prerequisites: List[List[int]]
:rtype: bool
"""
import collections
graph = collections.defaultdict(list)
numpre = [0] * numCourses
for i, j in prerequisites:
graph[j].append(i)
numpre[i] += 1
q = []
for i in range(len(numpre)):
if numpre[i] == 0:
q.append(i)
total = 0
while q:
cur = q.pop(0)
total += 1
for i in range(len(graph[cur])):
numpre[graph[cur][i]] -= 1
if not numpre[graph[cur][i]]:
q.append(graph[cur][i])
return total == numCourses