写在前面:
下周要考试了,紧张!赶紧复习一下考试要点。选取题目210,是第四周做的那道的升级版,练练手。
题意解读:
给定numCourses个课程以及课程的学习次序对集合,【0,1】代表需先学完1再学习0.
求输出正确的学习顺序,如果不能学完所有课程,则输出空集合。
解题思路:
将每个课程视为一个点,学习顺序变成点与点之间点有向边。
如果这些课程存在环,则不能学完。如果不存在环,则能学完。
回归一下图论的内容,存在环的特点是环内所有点的入度(其他点指向这个点的数量)都不为0.
本次要求数据课程的学习次序,也即是输出有向无环图的拓扑排序。
主要思路是先用inLine记录所有点的入度数,用map记录各个点指向的点。
每次处理当前inLine为0的点(不需要先学其他课程的课程),
用pStack记录课程顺序,将处理的点压栈,删除这个点——inLine标记为-1,将其指向的点入度减1.
循环再处理入度为0的点。。。。一直到找不到入度为0的点。
这时候需要判断两种情况:所有点都处理过了、inLine都是-1,pStack就是所得答案;
另一种是存在环,存在不等于-1的点,则需清空pStack再return。
代码:
class Solution {
public:
vector<int> findOrder(int numCourses, vector<pair<int, int>>& prerequisites) {
inLine.resize(numCourses);
for(int i = 0; i < numCourses; i++) inLine[i] = 0;
//pStack.resize(numCourses);
map.resize(numCourses);
for(int i = 0; i < prerequisites.size(); i++)
{
map[prerequisites[i].second].push_back(prerequisites[i].first);
inLine[prerequisites[i].first] +=1;
}
for(int i = 0; i < inLine.size();)
{
if(inLine[i] == 0)
{
pStack.push_back(i);
for(int j=0; j<map[i].size(); j++)
{
inLine[map[i][j]] -=1;
}
inLine[i] = -1;
i = 0;
}
else
i+=1;
}
for(int i = 0; i < inLine.size();i++) if(inLine[i] != -1){pStack.clear(); break;}
return pStack;
}
private:
vector<int> inLine;
vector<int> pStack;
vector<vector<int>> map;
};