你这个学期必须选修 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 <= numCourses <= 105
0 <= prerequisites.length <= 5000
prerequisites[i].length == 2
0 <= ai, bi < numCourses
prerequisites[i]
中的所有课程对 互不相同
C++ class Solution {private : vector<vector<int >> edges; vector<int > visited; bool valid = true ; public : void dfs (int u) { visited[u] = 1 ; for (int v: edges[u]) { if (visited[v] == 0 ) { dfs (v); if (!valid) { return ; } } else if (visited[v] == 1 ) { valid = false ; return ; } } visited[u] = 2 ; } bool canFinish (int numCourses, vector<vector<int >>& prerequisites) { edges.resize (numCourses); visited.resize (numCourses); for (const auto & info: prerequisites) { edges[info[1 ]].push_back (info[0 ]); } for (int i = 0 ; i < numCourses && valid; ++i) { if (!visited[i]) { dfs (i); } } return valid; } };
Python
class Solution (object ): def canFinish (self, numCourses, prerequisites ): """ :type numCourses: int :type prerequisites: List[List[int]] :rtype: bool """ self.edges = [] self.visited = [] self.valid = True def dfs (u ): self.visited[u] = 1 for v in self.edges[u]: if self.visited[v] == 0 : dfs(v) if not self.valid: return if self.visited[v] == 1 : self.valid = False return self.visited[u] = 2 self.edges = [[] * numCourses] * numCourses self.visited = [0 ] * numCourses for info in prerequisites: self.edges[info[1 ]].append(info[0 ]) for i in range (numCourses): if self.valid and not self.visited[i]: dfs(i) return self.valid
现在你总共有 numCourses
门课需要选,记为 0
到 numCourses - 1
。给你一个数组 prerequisites
,其中 prerequisites[i] = [ai, bi]
,表示在选修课程 ai
前 必须 先选修 bi
。
例如,想要学习课程 0
,你需要先完成课程 1
,我们用一个匹配来表示:[0,1]
。
返回你为了学完所有课程所安排的学习顺序。可能会有多个正确的顺序,你只要返回 任意一种 就可以了。如果不可能完成所有课程,返回 一个空数组 。
示例 1:
输入:numCourses = 2 , prerequisites = [[1,0]] 输出:[0 ,1 ] 解释:总共有 2 门课程。要学习课程 1 ,你需要先完成课程 0 。因此,正确的课程顺序为 [0 ,1 ] 。
示例 2:
输入:numCourses = 4, prerequisites = 输出: 解释:总共有 4 门课程。要学习课程 3,你应该先完成课程 1 和课程 2。并且课程 1 和课程 2 都应该排在课程 0 之后。 因此,一个正确的课程顺序是 。另一个正确的排序是 。
示例 3:
输入:numCourses = 1, prerequisites = 输出:
提示:
1 <= numCourses <= 2000
0 <= prerequisites.length <= numCourses * (numCourses - 1)
prerequisites[i].length == 2
0 <= ai, bi < numCourses
ai != bi
所有[ai, bi]
互不相同
注意
C++ class Solution {public : vector<vector<int >> edges; vector<int > visited; bool valid = true ; stack<int > stk; vector<int > res; vector<int > findOrder (int numCourses, vector<vector<int >>& prerequisites) { edges.resize (numCourses); visited.resize (numCourses); for (auto & info : prerequisites){ edges[info[1 ]].push_back (info[0 ]); } for (int i = 0 ; i < numCourses && valid; ++i) { if (!visited[i]) { dfs (i); } } while (!stk.empty ()){ res.push_back (stk.top ()); stk.pop (); } if (res.size ()!= numCourses) return {}; return res; } void dfs (int u) { visited[u] = 1 ; for (auto & v : edges[u]){ if (visited[v] == 0 ) dfs (v); if (!valid) { return ; } if (visited[v] == 1 ){ valid = false ; return ; } } visited[u] = 2 ; stk.push (u); } };