描述
你需要去上n门九章的课才能获得offer,这些课被标号为 0
到 n-1
。
有一些课程需要“前置课程”,比如如果你要上课程0,你需要先学课程1,我们用一个匹配来表示他们: [0,1]
给你课程的总数量和一些前置课程的需求,返回你为了学完所有课程所安排的学习顺序。
可能会有多个正确的顺序,你只要返回一种就可以了。如果不可能完成所有课程,返回一个空数组。
您在真实的面试中是否遇到过这个题? 是
题目纠错
样例
给定 n = 2
, prerequisites = [[1,0]]
返回 [0,1]
给定 n = 4, prerequisites = [1,0],[2,0],[3,1],[3,2]]
返回 [0,1,2,3]
or [0,2,1,3]
源代码如下:
class Solution {
public:
/*
* @param numCourses: a total of n courses
* @param prerequisites: a list of prerequisite pairs
* @return: the course order
*/
struct Edge{ //边结点的定义
int dest; //边的另一顶点位置
Edge *link; //下一条边链指针
Edge() {} //构造函数
Edge(int num){ //构造函数
dest = num;
link = NULL;
}
bool operator != (Edge &R)const{ //判边不等否。#只能用于同一行的单链表中
return (dest != R.dest);
}
};
//顶点的定义
struct Vertex{
int data; //顶点的名字
Edge *adj; //边链表的头指针
};
int numVertices=0;
int numEdges=0;
Vertex *NodeTable; //创建顶点表数组
int NumberOfVertices(){ //返回当前顶点数
return numVertices;
}
int getValue(int i){ //返回该邻接顶点的编号,若不存在则返回0 //取位置为i的顶点中的值
return (i >= 0 && i < NumberOfVertices()) ? NodeTable[i].data : 0;
}
int getFirstNeighbor(int v){
if (v != -1){ //顶点v存在
Edge *p = NodeTable[v].adj; //对应边链表第一个边结点
if (p != NULL){ //存在, 返回第一个邻接顶点
return p->dest;
}
}
return -1; //第一个邻接顶点不存在
}
int getNextNeighbor(int v, int w){
if (v != -1){ //顶点v存在
Edge *p = NodeTable[v].adj; //对应边链表第一个边结点
while (p != NULL && p->dest != w){ //寻找邻接顶点w
p = p->link;
}
if (p != NULL && p->link != NULL){
return p->link->dest; //返回下一个邻接顶点
}
}
return -1; //下一邻接顶点不存在
}
bool insertEdge(int v1, int v2){
// if (v1 >= 0 && v1 < numVertices && v2 >= 0 && v2 < numVertices){
Edge *q, *p = NodeTable[v1].adj; //v1对应的边链表头指针
while (p != NULL && p->dest != v2){ //寻找邻接顶点v2
p = p->link;
}
if (p != NULL){ //找到此边, 不插入
return false;
}
p = new Edge; //否则, 创建新结点
q = new Edge;
p->dest = v2;
p->link = NodeTable[v1].adj; //链入v1边链表
NodeTable[v1].adj = p;
numEdges++;
return true;
// }
// return false;
}
void insertVertex(const int& vertex){
//在图的顶点表中插入一个新顶点vertex。若插入成功,函数返回true, 否则返回false。
NodeTable[numVertices].data = vertex; //插入在表的最后
numVertices++;
}
void fun(int numCourses) {
NodeTable = new Vertex[numCourses];
for (int i = 0; i < numCourses; i++) {
NodeTable[i].adj = NULL;
}
}
vector<int> findOrder(int numCourses, vector<pair<int, int>> &prerequisites) {
// write your code here
int numpre = prerequisites.size();
fun(numCourses);
for(int i=0;i<numCourses;i++){//插入顶点
insertVertex(i);
}
int i, j, w, v;
int top = -1; //入度为零顶点的栈初始化
int n = numCourses; //网络中顶点个数
numVertices = numCourses;
int *count = new int[n]; //入度数组兼入度为零顶点栈
for (i = 0; i < n; i++) count[i] = 0;
for (int p = 0; p < numpre; p++) {
i = prerequisites[p].first;
j = prerequisites[p].second;
if (i > -1 && i < n && j > -1 && j < n) {
if(insertEdge(i, j)){
count[j]++;
}
cout<<j<<count[j];
}
}
for (i = 0; i < n; i++) //检查网络所有顶点
if (count[i] == 0) //入度为零的顶点进栈
{
count[i] = top; top = i;
}
int num = 0;
vector<int>result(n);
for (i = 0; i < n; i++){ //期望输出n个顶点
if (top == -1) { //中途栈空,转出
cout << "网络中有回路!" << endl;
return vector<int>();
}
else { //继续拓扑排序
v = top; top = count[top]; //退栈v
//cout << getValue(v); //输出
result[num++] = getValue(v);
w = getFirstNeighbor(v);
while (w != -1) { //扫描顶点v的出边表
count[w]--; //邻接顶点入度减一
if (!count[w]) //入度减至零,进栈
{
count[w] = top; top = w;
}
w = getNextNeighbor(v, w);
} //一个顶点输出后,调整其邻接顶点入度
} //输出一个顶点,继续for循环
}
vector<int>finresult(num);
for(int fin=0;fin<num;fin++){
finresult[fin]=result[num-fin-1];
}
return finresult;
}
};