题目描述
你这个学期必须选修 numCourses
门课程,记为 0
到 numCourses - 1
。
在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites
给出,其中 prerequisites[i] = [ai, bi]
,表示如果要学习课程 ai
则 必须 先学习课程 bi
。
- 例如,先修课程对
[0, 1]
表示:想要学习课程0
,你需要先完成课程1
。
请你判断是否可能完成所有课程的学习?如果可以,返回 true
;否则,返回 false
。
示例 1:
输入:numCourses = 2, prerequisites = [[1,0]] 输出:true 解释:总共有 2 门课程。学习课程 1 之前,你需要完成课程 0 。这是可能的。
示例 2:
输入:numCourses = 2, prerequisites = [[1,0],[0,1]] 输出:false 解释:总共有 2 门课程。学习课程 1 之前,你需要先完成课程 0 ;并且学习课程 0 之前,你还应先完成课程 1 。这是不可能的。
思路
1)定义一个入度数组,用来存储 prerequisites[1]这些节点的入度个数
2)定义一个邻接表,用来存储 prerequisites[0]连接着哪些节点
3)定义一个队列,先把入度为0的放入队列中
4)弹出队首节点,count+=1,查邻接表看后面要学的课程
5)在入度数组中纷纷减去1,因为前面的课程学完了
6)如果有课程入度为0,则放入队列
7)判断count==numCourses
from collections import deque
class Solution(object):
def canFinish(self, numCourses, prerequisites):
"""
:type numCourses: int
:type prerequisites: List[List[int]]
:rtype: bool
"""
in_degree = [0] * numCourses # 入度数组
adj_list = {} # 邻接表
# 构建入度数组和邻接表
for pre in prerequisites:
in_degree[pre[0]] += 1
if pre[1] in adj_list:
adj_list[pre[1]].append(pre[0])
else:
adj_list[pre[1]] = [pre[0]]
queue = deque()
for i in range(numCourses):
if in_degree[i] == 0: # 所有入度为0的课入列
queue.append(i)
count = 0
while queue:
selected = queue.popleft() # 当前选的课,出列
count += 1 # 选课数+1
to_enqueue = adj_list.get(selected, []) # 获取这门课对应的后续课
for course in to_enqueue:
in_degree[course] -= 1 # 依赖它的后续课的入度-1
if in_degree[course] == 0: # 如果因此减为0,入列
queue.append(course)
return count == numCourses # 选了的课等于总课数,true,否则false
if __name__ == "__main__":
s = Solution()
numCourses = 6
prerequisites = [[3, 0], [3, 1], [4, 1], [4, 2], [5, 3], [5, 4]]
print(s.canFinish(numCourses, prerequisites))