Leetcode 207. 课程表

浅浅的花香味﹌ 2023-02-14 03:01 152阅读 0赞

Leetcode 207. 课程表

  • 1、问题分析
  • 2、问题解决
  • 3、总结

1、问题分析

题目链接:https://leetcode-cn.com/problems/course-schedule/
  本质上就是一个拓扑排序问题。代码我已经进行了详细的注释,理解应该没有问题,读者可以作为参考,如果看不懂(可以多看几遍),欢迎留言哦!我看到会解答一下。

2、问题解决

  笔者以C++方式解决。

  1. #include "iostream"
  2. using namespace std;
  3. #include "algorithm"
  4. #include "vector"
  5. #include "queue"
  6. #include "set"
  7. #include "map"
  8. #include "string"
  9. #include "stack"
  10. class Solution {
  11. private:
  12. // 图的邻接表
  13. vector<vector<int>> Adj;
  14. // 顶点入度数
  15. vector<int> inDegree;
  16. // 全局节点数目
  17. int n_all;
  18. public:
  19. bool canFinish(int numCourses, vector<vector<int>> &prerequisites) {
  20. // 如果只有一门或没有课,肯定可以完成所有课程的学习
  21. if (numCourses <= 1) {
  22. return true;
  23. }
  24. // 初始化邻接矩阵
  25. Adj.resize(numCourses);
  26. // 初始化入度数组
  27. inDegree.resize(numCourses);
  28. // 初始化全局节点数目
  29. n_all = numCourses;
  30. // 给邻接矩阵和入度数组赋值
  31. init(prerequisites);
  32. // 返回拓扑排序结果
  33. return topologicalSort(numCourses);
  34. }
  35. void init(vector<vector<int>> &prerequisites) {
  36. for (int i = 0; i < prerequisites.size(); ++i) {
  37. // a ---> b ,说明 a 的邻接矩阵中应该有 b 节点
  38. Adj[prerequisites[i][0]].push_back(prerequisites[i][1]);
  39. // 同时 b 节点的入度 + 1
  40. inDegree[prerequisites[i][1]] += 1;
  41. }
  42. }
  43. /** * 拓扑排序 * @param numCourses 顶点数目 * @return */
  44. bool topologicalSort(int numCourses) {
  45. // 记录加入拓扑排序的节点数
  46. int num = 0;
  47. // 保存所有入度为 0 的节点
  48. queue<int> q;
  49. for (int i = 0; i < n_all; ++i) {
  50. // 首先将所有入度为 0 的节点入队
  51. if (inDegree[i] == 0) {
  52. q.push(i);
  53. }
  54. }
  55. // 当还有入度为 0 的节点时,进行如下操作
  56. while (!q.empty()) {
  57. // 首先取出队头元素
  58. int u = q.front();
  59. q.pop();
  60. // 将所有以该节点头 尾结点的入度 - 1
  61. // 例如 a ----> b ,a 为尾结点,将 b 节点的入度 -1
  62. // 而 b 节点正好存储在 a 节点的邻接表中
  63. for (int i = 0; i < Adj[u].size(); ++i) {
  64. // 取出节点 b
  65. int v = Adj[u][i];
  66. // b 节点的入度 -1
  67. inDegree[v]--;
  68. // 如果 - 1 之后节点的入度为 0 ,继续加入到 队列中
  69. if (inDegree[v] == 0) {
  70. q.push(v);
  71. }
  72. }
  73. // 拓扑排序过的节点 + 1
  74. num++;
  75. }
  76. // 判断是否所有的节点都经历过拓扑排序,
  77. // 如果是,说明可能完成所有课程的学习
  78. // 否则不能完成所有课程的学习
  79. return num == numCourses;
  80. }
  81. };
  82. int main() {
  83. int numCourses = 2;
  84. vector<vector<int>> prerequisites = { { 1, 0},
  85. { 0, 1}};
  86. Solution *pSolution = new Solution;
  87. bool b = pSolution->canFinish(numCourses, prerequisites);
  88. cout << b << endl;
  89. system("pause");
  90. return 0;
  91. }

运行结果

在这里插入图片描述

有点菜,有时间再优化一下。

3、总结

  难得有时间刷一波LeetCode, 这次做一个系统的记录,等以后复习的时候可以有章可循,同时也期待各位读者给出的建议。算法真的是一个照妖镜,原来感觉自己也还行吧,但是算法分分钟教你做人。前人栽树,后人乘凉。在学习算法的过程中,看了前辈的成果,受益匪浅。
感谢各位前辈的辛勤付出,让我们少走了很多的弯路!
哪怕只有一个人从我的博客受益,我也知足了。
点个赞再走呗!欢迎留言哦!

发表评论

表情:
评论列表 (有 0 条评论,152人围观)

还没有评论,来说两句吧...

相关阅读

    相关 207.课程表

    打卡!!!每日一题 今天给大家分享一道拓扑排序的问题,本题也是一道经典的「拓扑排序」问题,通过这道题也顺便帮大家拓展一下拓扑排序的知识。 题目描述: > 你这个学期必须选

    相关 拓扑排序-leetcode207课程表

    现在你总共有 n 门课需要选,记为 0 到 n-1。 在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: \[