题目:
There are a total of n courses you have to take, labeled from 0 to n - 1.
Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is >expressed as a pair: [0,1]
Given the total number of courses and a list of prerequisite pairs, return the ordering of courses you should take >to finish all courses.
There may be multiple correct orders, you just need to return one of them. If it is impossible to finish all courses, >return an empty array.
For example:
2, [[1,0]]
There are a total of 2 courses to take. To take course 1 you should have finished course 0. So the correct course >order is [0,1]
4, [[1,0],[2,0],[3,1],[3,2]]
There are a total of 4 courses to take. To take course 3 you should have finished both courses 1 and 2. Both >courses 1 and 2 should be taken after you finished course 0. So one correct course order is [0,1,2,3]. Another >correct ordering is[0,2,1,3].
这道题是一个典型的拓扑排序问题。首先对于所有的course构成的有向图G(V, E)来说,最先选择的课程一定是没有先修课程的course,用图论的语言来表述就是入度为零。这样我们只要维护一个有向图,每次从中删除一个入度为零的点及其连接的边,将其加入到结果中去。当这个图为空时边求出了这个问题的一个解。但是,当这个图不为空又不存在入度为零的点时,说明这个图中存在环,即不存在解。代码如下:
class Solution {
public:
vector<int> findOrder(int numCourses, vector<pair<int, int>>& prerequisites) {
int pre[numCourses];
for (int i=0; i<numCourses; i++) pre[i]=0;
vector<vector<int>> adj(numCourses);
for (int i=0; i<prerequisites.size(); i++) {
pair<int, int>& tmp = prerequisites[i];
adj[tmp.second].push_back(tmp.first);
pre[tmp.first]++;
}
vector<int> result;
int count = 0;
while(count != numCourses) {
count = 0;
for(int i=0; i<numCourses; i++) if (pre[i]==0) {
pre[i]=-1;
vector<int> tmp = adj[i];
for(int j=0; j<tmp.size(); j++) pre[tmp[j]]--;
result.push_back(i);
} else count++;
}
if (result.size()!=numCourses) result ={};
return result;
}
};
这其中我用一个pre数组来维护每个点的入度,用count在每次迭代的时候记录入度非零的点的个数。由于每次从图中删除一个点时,将其入度修改为-1,所以不存在入度为零的点只有两种情况:得到了正确解或者图中存在环所以不存在解。所以在最后检查结果的大小是否与course的个数相等来判定这两种情况。