显然,将课程看成一些点,课程的关系看成边,这个问题就等价于判断一个有向图是否有环,可以用标准的拓扑排序来解决。拓扑排序的思路如下:
1. 先用临接表的方法建立图,然后算出每个点的入度
2. 用BFS的思想,先将入度为0的点入队
3. 每次从队头拿出一个点,将对应的临接点的入度--
4. 如果入度减到0就入队
5. 如果没有环,一定可以完成拓扑排序,如果有环,拓扑排序不能完成,有的点不会入队。
6. 通过比较出队的点和总的点的关系,判断是否有环。
class Solution {
private:
vector<vector<int>> edges; // 邻接表
vector<int> indeg; // 入度表
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
edges.resize(numCourses);
indeg.resize(numCourses);
for(auto info:prerequisites){
edges[info[1]].push_back(info[0]);
indeg[info[0]]++;
}
queue<int> q;
for (int i = 0; i < numCourses; ++i) {
if (indeg[i] == 0) {
q.push(i);
}
}
int visited = 0;
while (!q.empty()) {
++visited;
int u = q.front();
q.pop();
for (int v: edges[u]) {
--indeg[v];
if (indeg[v] == 0) {
q.push(v);
}
}
}
return visited==numCourses;
}
};
210在207的基础上输出方案,比较简单
class Solution {
private:
vector<vector<int>> edges;
vector<int> indeg;
public:
vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
edges.resize(numCourses);
indeg.resize(numCourses);
for(auto info:prerequisites){
edges[info[1]].push_back(info[0]);
indeg[info[0]]++;
}
queue<int> q;
for(int i=0;i<numCourses;i++){
if(indeg[i]==0){
q.push(i);
}
}
int visited = 0;
vector<int> res;
while(!q.empty()){
int tmp = q.front();
q.pop();
visited++;
res.push_back(tmp);
for(auto pos:edges[tmp]){
indeg[pos]--;
if(indeg[pos]==0) q.push(pos);
}
}
if(visited==numCourses) return res;
else return {};
}
};