目录
菜鸟做题,语言是 C++
含义:根据节点之间的依赖关系来生成一个有序的序列。
应用:
突然想起来好像在操作系统原理里学过!
排序步骤:
名词解释:
如果图中不再存在入度为 0 的节点,且并非所有的节点都被加入到排序结果中,那么说明原图中存在环。综上,拓扑排序的主要功能是帮助安排顺序,顺带帮助检测图中有没有环。
下图描述了一个拓扑排序过程。
① 入度为 0 的节点有 B、D,我们任意选择 B,并删除它的出边:

② 入度为 0 的节点有 A、D,我们任意选择 A,并删除它的出边;更新后,入度为 0 的节点有 C、D,我们任意选择 C,并删除它的出边:

③ 入度为 0 的节点有 D,我们选择 D,并删除它的出边;更新后,入度为 0 的节点有 F,我们选择 F,并删除它的出边:

以此类推,不再赘述。通过 “任意选择” 一词可以看出,拓扑排序的结果不止一种。
感觉解题方法和拓扑排序关系不大,更多的是从题意出发;想了很久要怎么才能把思路表述清楚,最终认为还是看代码来得快 TT
解题思路:假设有先修课程对 [0,1] 和 [0,2]
访问状态:
针对 “该门课程正在被学习” 的说法,需要说明的是,这是算法题而不是现实生活!如果一门课正在被学习,不是代表学习它需要一段时间,而是代表它的先修课程不可能被修完,导致我们永远学不了它。
- class Solution {
- public:
- vector<int> visited;
- vector
int>> mustFinish; - bool possible = true;
-
- void helper(int course) {
- // 指明该门课程正在被学习
- visited[course] = 1;
- // 判断其先修课程是否已被修完
- for (auto & preCourse : mustFinish[course]) {
- // 递归访问未被学习的先修课程
- if (visited[preCourse] == 0) {
- helper(preCourse);
- if (!possible) return;
- // 先修课程正在被学习(因为卡住了)
- } else if (visited[preCourse] == 1) {
- possible = false;
- return;
- }
- }
- // 指明该门课程已经被学习
- visited[course] = 2;
- }
-
- bool canFinish(int numCourses, vector
int >>& prerequisites) { - visited.resize(numCourses);
- mustFinish.resize(numCourses);
-
- // 获取每门课程的先修课程数组
- for (auto & p : prerequisites) {
- mustFinish[p[0]].push_back(p[1]);
- }
- // 循环访问每门课程
- for (int i = 0; i < numCourses && possible; ++i) {
- helper(i);
- }
-
- return possible;
- }
- };
在 207. 课程表 的基础上,增加一个数据结构来存储课程顺序即可。
唯一区别在于:
for (int i = 0; i < numCourses && possible && !visited[i]; ++i)
新增条件 !visited[i],不允许已经被访问过的课程再被访问,避免了课程重复被学习。
- class Solution {
- public:
- vector<int> visited;
- vector
int>> mustFinish; - bool possible = true;
- vector<int> ans;
-
- void helper(int course) {
- visited[course] = 1;
- for (auto & preCourse : mustFinish[course]) {
- if (visited[preCourse] == 0) {
- helper(preCourse);
- if (!possible) return;
- } else if (visited[preCourse] == 1) {
- possible = false;
- return;
- }
- }
- visited[course] = 2;
- ans.push_back(course);
- }
-
- vector<int> findOrder(int numCourses, vector
int >>& prerequisites) { - visited.resize(numCourses);
- mustFinish.resize(numCourses);
-
- for (auto & p : prerequisites) {
- mustFinish[p[0]].push_back(p[1]);
- }
-
- for (int i = 0; i < numCourses && possible && !visited[i]; ++i) {
- helper(i);
- }
-
- if (possible) return ans;
- return {};
- }
- };