207. 课程表
方法
class Solution {
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
// 记录节点的入度:[1,0]表示学完了前导课0再能学后续课1,所以1的入度是1,0的入度是0;用vector存储,刚好下标就相当于课的索引,数组中下标对应的值就是入度,即该课程的前导课的数量。
vector<int> inDegree(numCourses, 0);
// 整理图中的前导课和后续课的关系
unordered_map<int, vector<int>> preRearCourses;
for(auto prerequisite : prerequisites){
// 记录入度,比如[3,0][3,1],先上完0和1才能上3,所以遍历到的每一对,第一个值的数值++,即入度++
inDegree[prerequisite[0]]++;
// 添加依赖于prerequisite[1]课的后续课;因为BFS时每次入队的是入度为0的前导课,所以这里以前导课为索引,记录后续课,方便通过入队的前导课找到后续课
preRearCourses[prerequisite[1]].push_back(prerequisite[0]);
}
// 用队列实现BFS,每次都遍历入度为0的课
queue<int> coursesQueue;
for(int i = 0; i < numCourses; i++){
// 将入度为0的课放入队列
if(inDegree[i] == 0){
coursesQueue.push(i);
}
}
while(!coursesQueue.empty()){
// 用于最后判断是否把所有要学的课都学了
numCourses--;
// 取出队首的前导课,表示学完了这门课,更新依赖于这门课的后续课的依赖数量,即入度
int preCourse = coursesQueue.front();
coursesQueue.pop();
// 更新所有与之关联的后续课的入度;preCourse是前导课,preRearCourses[preCourse]是对应的后续课;
for(int i = 0; i < preRearCourses[preCourse].size(); i++){
if(inDegree[preRearCourses[preCourse][i]] > 0){
// preRearCourses[preCourse]课的前导课preCourse学完了,所以preRearCourses[preCourse]的入度就能--;
inDegree[preRearCourses[preCourse ][i]]--;
// 将入度降至0的课程加入队列;
if(inDegree[preRearCourses[preCourse ][i]] == 0){
coursesQueue.push(preRearCourses[preCourse ][i]);
}
}
}
}
return numCourses == 0 ;
}
};