方法一: 广度优先遍历BFS,递归
class Solution {
public:
//入度矩阵
vector<int> indegree;
vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
//1. 构建图以及入度矩阵
indegree.resize(numCourses);
vector<vector<int>> graph(numCourses);
graph = graphBuild(numCourses, prerequisites);
//2. 初始化“记录遍历的节点”的矩阵
vector<int> res;
int cur;//当前节点
//3. 新建队列,记录遍历的节点(类似层序遍历的过程)
queue<int> q;
//4. 将入度为0的节点都加入队列,针对有写节点是孤立的情况
for(int i = 0; i < numCourses; i++){
if(indegree[i] == 0){
q.push(i);
}
}
//5. 遍历所有节点
//当队列非空时,将入度非0的相邻节点加入队列中
//如果是无环的图,那么所有的节点都会被加入队列中
//如果存在环,则必然有节点的入度>=2,且无法被消除(画图"0->1->2->3->1"和"0->1->2->3&1->4->3"可以看出区别,对前者而言,3的入度会变为0,而对后者而言,1的入度从2变到1后无法下降,无法进入队列)
while(!q.empty()){
cur = q.front();
res.push_back(cur);
q.pop();
//遍历每个相邻的节点
for(auto info : graph[cur]){
indegree[info]--;
if(indegree[info] == 0){
//如果节点info没有依赖的节点了,就把他插入队列中
q.push(info);
}
}
}
//6. 当遍历可以经过所有节点时,说明是无向环
if(res.size() == numCourses){
return res;
}else{
return {};
}
}
//创建图的邻接表以及入度矩阵
vector<vector<int>> graphBuild(int numCourses, vector<vector<int>>& prerequisites){
vector<vector<int>> graph;
graph.resize(numCourses);
for(auto& info : prerequisites){
graph[info[1]].push_back(info[0]);
indegree[info[0]]++;
}
return graph;
}
};
方法一:深度优先遍历,递归(与题目207. 课程表相同,在我的力扣账号的207题分享上有详细的介绍,这里省略)
class Solution {
public:
//初始化:记录是否访问过,路径有哪些节点,是否为环,遍历过的数据
vector<bool> visit;
vector<bool> path;
bool flag = 0;
vector<int> result;
vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
if(numCourses <= 1) return {0};
//1.初始化数据
visit.resize(numCourses);
path.resize(numCourses);
//2.创建图的邻接表
vector<vector<int>> graph = graphBuild(numCourses, prerequisites);
//3.遍历每个节点
for(int i = 0; i < numCourses; i++){
if(flag == 1){
return {};
}else{
traverse(graph, i);
}
}
//4.处理后序遍历得到的结果(逆转),原因,自己画一个图看看
reverse(result.begin(), result.end());
return result;
}
//创建图的邻接表
vector<vector<int>> graphBuild(int numCourses, vector<vector<int>>& prerequisites){
vector<vector<int>> graph;
graph.resize(numCourses);
for(auto& info : prerequisites){
graph[info[1]].push_back(info[0]);
}
return graph;
}
//遍历每个节点
void traverse(vector<vector<int>>& graph, int s){
if(path[s]){
flag = 1;
return;
}
if(visit[s]){
return;
}
//更新记录
visit[s] = 1;
path[s] = 1;
for(auto i : graph[s]){
if(flag == 1){
return;
}else{
traverse(graph, i);
}
}
//记录后序遍历结果(与206不同之处)
result.push_back(s);
path[s] = 0;
}
};
我把自己写的C++代码分享出来,并给出了详细的代码注释,特别适合新手,尤其是对C++也不熟悉的人。欢迎阅读我在力扣上的账号:
leetcode-cn.com/u/mianhua1212/