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].
Note:
- The input prerequisites is a graph represented by a list of edges,
not adjacency matrices. Read more about how a graph is represented. You may assume that there are no duplicate edges in the input
prerequisites.题意:从0~n-1的n门课程,有优先次序,比如你要上课程0,必须先上课程1,则用pair:[0,1]来表示优先次序。问你能否完成所有课程。
样例:2 [[1,0]]
输出:[0,1]
样例:4, [[1,0],[2,0],[3,1],[3,2]]
输出:[0,1,2,3] 或者 [0,2,1,3]
注意:- 图用输入的prerequisites代表所有边
- 假设输入中没有重复边
class Solution {
public:
/*
* 1. 理清拓扑排序思路:
* (1) 从AOV网中选择一个没有前驱的顶点,输出它
* (2) 从AOV网中删除该顶点,并且删除以该顶点为尾的全部有向边
* (3) 重复上述两步,直到剩余的网中不再存在没有前驱的顶点为止
* 2. 如何解决这个问题?
* 先建立AOV网,选择邻接表法建图,之后进行拓扑排序。
* 3. 如何建图?使用什么数据结构?要注意什么?
* 数据结构:根据题目给出条件,我们可以使用vector<unordered_set<int>> graph建图
* 注意:由于要进行拓扑排序,我们建树时要记录每个节点的入度vector<int> indegrees(numCourses, 0)
* 建图:for pre in prerequisites: // <0,1> 1 -> 0 : to take course 0 you have to first take course 1
* graph[pre.second].insert(pre.first) // 插入节点
* indegrees[pre.first]++; // 弧尾入度++
* 4. 拓扑排序
*/
/* BFS:访问一个顶点,然后访问该顶点的其余邻接点 */
vector<int> findOrder(int numCourses, vector<pair<int, int>>& prerequisites) {
vector<unordered_set<int>> graph(numCourses); // 模拟邻接表
vector<int> indegrees(numCourses, 0); // 用于记录节点入度数
createGraph(graph, numCourses, prerequisites, indegrees);
// 拓扑排序
vector<int> plan(numCourses, 0);
stack<int> st;
int counter = 0; // 记录入度为0的节点数
// 入度为0的顶点入栈
for(int i = 0; i < numCourses; ++i)
if(!indegrees[i]) st.push(i);
while(!st.empty()){
int zeroIn = st.top(); // 弹出一个入度为0的顶点
st.pop();
plan[counter++] = zeroIn; // 入度为0的节点加入课程的安排次序*/
// 访问zeroIn的所有边
for(int next : graph[zeroIn]){
if(!(--indegrees[next])) // 弧头入度数减1变成了入度为0的顶点 (如1 -> 2,2即弧头)
st.push(next);
}
}
if(counter == numCourses) // 拓扑排序之后所有节点都可以入度为0,除非是非连通图
return plan;
else
return vector<int>();
}
void createGraph(vector<unordered_set<int>> &graph, int numCourses
, vector<pair<int, int>>& prerequisites, vector<int>& indegrees){
for(pair<int, int>& pre : prerequisites){
graph[pre.second].insert(pre.first); // 插入节点
indegrees[pre.first]++; // 弧尾入度++
}
}
};
分析时间复杂度和空间复杂度
与207.Course Schedule :http://write.blog.csdn.net/mdeditor#!postId=79633919
Approach Two相同
提交结果:19ms beats 71%