相关题目:
207. 课程表
210. 课程表 II
1462. 课程表 IV
class CourseSchedule:"""207.课程表https://leetcode.cn/problems/course-schedule/"""def __init__(self):# 记录⼀次递归堆栈中的节点self.onPath = []# 记录遍历过的节点,防⽌⾛回头路self.visited = []# 记录图中是否有环self.hasCycle = Falsedef buildGraph(self, numCourses: int, prerequisites: List[List[int]]) -> List[List[int]]:# 注意这两种新建对象的区别,前者是传的引用,后者是拷贝一个新的变量# graph = [[]] * numCoursesgraph = [[] for _ in range(numCourses)]for edge in prerequisites:src = edge[1]dst = edge[0]graph[src].append(dst)return graphdef canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:"""dfs:param numCourses::param prerequisites::return:"""graph = self.buildGraph(numCourses, prerequisites)self.visited = [False] * numCoursesself.onPath = [False] * numCoursesfor i in range(numCourses):self.traverse(graph, i)return not self.hasCycledef traverse(self, graph, i):if self.onPath[i]:self.hasCycle = Truereturnif self.visited[i]:returnself.visited[i] = Trueself.onPath[i] = Truefor t in graph[i]:self.traverse(graph, t)self.onPath[i] = Falsedef canFinish2(self, numCourses: int, prerequisites: List[List[int]]) -> bool:"""bfs:param numCourses::param prerequisites::return:"""graph = [[] for _ in range(numCourses)]indegree = [0] * numCoursesfor edge in prerequisites:src = edge[1]dst = edge[0]graph[src].append(dst)indegree[dst] += 1queue = []for i in range(numCourses):if indegree[i] == 0:queue.append(i)visited = 0while queue:cur = queue.pop(0)visited += 1for v in graph[cur]:indegree[v] -= 1if indegree[v] == 0:queue.append(v)# 最后只需要判断已访问的课程数是否等于课程总数即可return visited == numCourses
# 210. 课程表 II
class Solution:def __init__(self):self.hascycle = Falseself.postorder = []def buildGraph(self, numCourses: int, prerequisites: List[List[int]]) -> List[List[int]]:# 注意这两种新建对象的区别,前者是传的引用,后者是拷贝一个新的变量# graph = [[]] * numCoursesgraph = [[] for _ in range(numCourses)]for edge in prerequisites:src = edge[1]dst = edge[0]graph[src].append(dst)return graphdef findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:graph = self.buildGraph(numCourses, prerequisites)self.indegree = [0] * numCourses# 计算入度,和环检测算法相同for edge in prerequisites:dst = edge[0]self.indegree[dst] += 1# 根据入度初始化队列中的节点,和环检测算法相同queue = []for i in range(numCourses):if self.indegree[i] == 0:queue.append(i)res = [0] * numCourses# 记录遍历节点的顺序count = 0while queue:cur = queue.pop(0)# 弹出节点的顺序即为拓扑排序结果res[count] = curcount += 1for neighbor in graph[cur]:self.indegree[neighbor] -= 1if self.indegree[neighbor] == 0:queue.append(neighbor)# 存在环if count != numCourses:return []return res
# 1462. 课程表 IV
class Solution:def checkIfPrerequisite(self, numCourses: int, prerequisites: List[List[int]], queries: List[List[int]]) -> List[bool]:g = [[] for _ in range(numCourses)]indgree = [0] * numCoursesisPre = [[False] * numCourses for _ in range(numCourses)]for p in prerequisites:indgree[p[1]] += 1g[p[0]].append(p[1])q = []# 将入度为0的节点加入队列for i in range(numCourses):if indgree[i] == 0:q.append(i)while q:cur = q.pop(0)for ne in g[cur]:isPre[cur][ne] = Truefor i in range(numCourses):isPre[i][ne] = isPre[i][ne] or isPre[i][cur]indgree[ne] -= 1if indgree[ne] == 0:q.append(ne)res = []for query in queries:res.append(isPre[query[0]][query[1]])return res