使用dfs的思想,对每个课程进行搜索。
learn[class]
中存储当前课程的状态,共有三种可能:
learn[class] = -1
【未搜索】首次遇到class
,对其进行递归搜索learn[class] = 0
【搜索中】前序搜索过此class
但还未回溯,说明遇到环,无法完成学习learn[class] = 1
【已完成】此class
已被成功学习,无需操作
当某课程的所有前序课程,均为“已完成”状态时,将其标记为已完成。
附上代码:
class Solution {
public:
void dfs(vector<int>& learn, map<int,vector<int>>& req, int curr){
if(learn[curr] != -1) return;
learn[curr] = 0;
for(auto cla : req[curr]){
dfs(learn, req, cla);
if(learn[cla] != 1) return;
}
learn[curr] = 1;
}
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
vector<int> learn(numCourses, -1);
map<int,vector<int>> req;
for(int i=0; i<numCourses; i++) req[i] = vector<int>();
for(auto x : prerequisites) req[x[0]].push_back(x[1]);
for(int i=0; i<numCourses; i++){
if(learn[i] == 1) continue;
dfs(learn, req, i);
}
for(auto x : learn) if(x != 1) return false;
return true;
}
};
这道题在之前的基础上,要求输出选课的顺序。
典型的拓扑排序问题,也可以通过堆来做。
对每个课程记录还需上多少门课才能选,同时把所有0的课程加入堆中(不需要额外选课的课程)
则堆中的课程都是可以直接选择的,不断将堆中元素加入输出,并更新其他课程的所需课程。
代码:
class Solution {
public:
vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
queue<int> que;
vector<int> out;
vector<int> idx(numCourses, 0);
map<int, vector<int>> m;
for(int i=0; i<numCourses; i++) m[i] = vector<int>();
for(auto x : prerequisites) {
m[x[1]].push_back(x[0]);
idx[x[0]]++;
}
for(int i=0; i<numCourses; i++) if(idx[i] == 0) que.push(i);
while(!que.empty()){
int temp = que.front(); que.pop();
out.push_back(temp);
for(auto x : m[temp]) {
idx[x]--;
if(idx[x] == 0) que.push(x);
}
}
if(out.size() != numCourses) return vector<int>();
return out;
}
};