207. Course Schedule
题目解释:总共有n种的课你需要去上,这些课标号从0到n-1。你上某些课程之前需要有一些先修课程,如你想要参加课程0,那么你必须先学习完课程1,这个可以采用一个配对来表示:[0,1]。
给出总的课程数以及先修课程匹配对,判断一下,你是否能修完所有的课程?
Example 1:
Input: 2, [[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: 2, [[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.
解释:在给出的两个课程对中,课程0和课程1互为先修课程,所以对于你来说,是不可能修完所有的课程的。
题目分析:在这里我们先分析出pair的特点,以[0,1]举例:
这是两门课程,你想要修习课程0,那么你就必须先学习课程1,即是1->0
看到这样的表示,我们应该是有一些感触的。这种表示方式是不是和我们学习的有向图很类似,在本题中,如果所有的结点都组合起来能够围成一个有向无环图,那么我们就是能够修习完所有的课程。这样我们的问题就变成了查看给定的图是否是是无环图。那么我们首先是需要构建图,然后根据拓扑排序来解决。
PS:本题讲道理来说,还是很难的,因为我们需要自己构建图,然后来判断构建的图是否是有环,但是难着难着感觉我们就习惯了,多看两遍,然后有了手感,写一下,就会发现整体来说,我们还是能解决的,索然过程还是比较痛苦的,但是这也是在代表着我们在进步,不是么?(手动打鸡血......)
class Solution(object):
def canFinish(self, numCourses, prerequisites):
"""
采用BFS
:type numCourses: int
:type prerequisites: List[List[int]]
:rtype: bool
"""
graph=collections.defaultdict(list)
indegrees=collections.defaultdict(int)
# 组建一幅图,其中u是相当于结点的第一个点,v是结点的第二条点,这就是graph代表的意义
# 这里是先修课程,如[1,0]代表要修1,就要先修0,所以理解好入度和出度的关系,indegrees代表入度
# 初始化建图
for u,v in prerequisites:
graph[v].append(u)
indegrees[u]+=1
for i in range(numCourses):
zero_degree=False
for j in range(numCourses):# 若某个结点的入度为0
if indegrees[j]==0:
zero_degree=True
break
if not zero_degree:
return False
# 结点j的入度减去1,同时在图中j指向的结点的入度减去1
indegrees[j]-=1
for node in graph[j]:
indegrees[node]-=1
return True
另外,用了BFS,我们同样可以尝试DFS。
def canFinish1(self, N, prerequisites):
"""
:type N,: int
:type prerequisites: List[List[int]]
:rtype: bool
"""
graph = collections.defaultdict(list)
for u, v in prerequisites:
graph[u].append(v)
# 0 = Unknown, 1 = visiting, 2 = visited
visited = [0] * N
for i in range(N):
if not self.dfs(graph, visited, i):
return False
return True
def dfs(self, graph, visited, i):
if visited[i] == 1:
return False
if visited[i] == 2:
return True
visited[i] = 1
for j in graph[i]:
if not self.dfs(graph, visited, j):
return False
visited[i] = 2
return True