LeetCode 207. Course Schedule
来源:互联网 发布:c语言赋值语句规则 编辑:程序博客网 时间:2024/05/21 06:46
图和dfs
LeetCode第207题CourseSchedule 难度Medium
题目描述:
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, is it possible for you to finish all courses?
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 it is possible.
2, [[1,0],[0,1]]
There are a total of 2 courses to take. To take course 1 you should have finished course 0, and to take course 0 you should also have finished course 1. So it is impossible.
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.
这题的相当于给定一个有向图,课程是有向图的顶点,课程之间的依赖关系相当于有向图的边。修完所有课程的顺序相当于对图进行一次拓扑排序。而问题问的是能否修完课程,即能否进行拓扑排序。若不能进行拓扑排序,说明有向图中有环,也就是存在回边(back edge)。
因此先由输入数据构建起有向图(邻接表形式),找出图中所有的源。
1. 若没有源,则图中只有环,返回false。
2. 若存在源,分别从每个源开始进行dfs。在dfs的过程中,访问顶点n时将pre[n]标志为true,离开时将post[n]标志为true。倘若将要访问的下一个顶点m的pre[m]为true而post[m]为false,则说明在dfs过程构建的树中,n是m的子树中的节点,故n->m的边是回边,以此可以判断图中有环,返回false。从所有源开始遍历完后,要检查是否顶点全部被遍历过,以排除有些环无源未被遍历的情况。
具体代码如下:
struct Node { int value; Node* next; Node(int v): value(v), next(NULL) {}};class Solution {public: bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) { constructGraph(numCourses, prerequisites); int s, i; for (i = 0; i < numCourses; i++) { pre.push_back(false); post.push_back(false); } // dfs每个源 for (s = 0; s < numCourses; s++) { if (source[s]) { if (dfs(s) == false) return false; } } // 判断是否所有顶点都被访问过 for (i = 0; i < numCourses; i++) { if (pre[i] == false) break; } destructGraph(numCourses); if (i == numCourses) return true; else return false; }private: bool constructGraph(int numCourses, vector<pair<int, int>>& prerequisites) { for (int i = 0; i < numCourses; i++) { adjList.push_back(NULL); source.push_back(true); } for (int i = 0; i < prerequisites.size(); i++) { Node* p = adjList[prerequisites[i].first]; // 有入边的顶点不是源 source[prerequisites[i].second] = false; if (p == NULL) { adjList[prerequisites[i].first] = new Node(prerequisites[i].second); } else { while (p->next != NULL) { p = p->next; } p->next = new Node(prerequisites[i].second); } } return true; } bool destructGraph(int numCourses) { for (int i = 0; i < numCourses; i++) { if (adjList[i] != NULL) { Node* del = adjList[i]; Node* p = del->next; while (p != NULL) { delete del; del = p; p = del->next; } delete del; } } return true; } bool dfs(int n) { pre[n] = true; Node* p = adjList[n]; // 判断这条边是否是回边 if (pre[p->value] == true && post[p->value] == false) return false; if (pre[p->value] == false) { if (dfs(p->value) == false) return false; } p = p->next; } post[n] = true; return true; }private: //邻接表 vector<Node*> adjList; //储存pre和post标志 vector<bool> pre; vector<bool> post; //储存源 vector<bool> source;};
结果:
37 / 37 test cases passed.
Status: Accepted
Runtime: 12 ms
Your runtime beats 86.48 % of cpp submissions.
是图和dfs很基础的应用的题目~
- [leetcode] 207.Course Schedule
- Leetcode 207. Course Schedule
- 207. Course Schedule LeetCode
- leetcode 207. Course Schedule
- leetcode.207. Course Schedule
- LeetCode 207. Course Schedule
- 【LeetCode】207. Course Schedule
- [leetcode] 207. Course Schedule
- leetcode-207. Course Schedule
- leetcode 207. Course Schedule
- [LeetCode] 207. Course Schedule
- 【Leetcode】207. Course Schedule
- Leetcode 207. Course Schedule
- LeetCode 207.Course Schedule
- Leetcode 207. Course Schedule
- Leetcode 207. Course Schedule
- [LeetCode]207. Course Schedule
- Leetcode 207. Course Schedule
- mysql对表列数和行大小的限制
- 新手微信开发心得
- vim显示空格
- 【软考之旅】第一章 计算机系统知识
- express mock 服务端数据
- LeetCode 207. Course Schedule
- 学习aop的底层设计
- 面向对象 < const > 常量定义 与 < instanceof > 判断实例化
- 努比亚Z17S将重新定义全面屏,你觉得这样可以吗?
- tomcat部署两个项目只有一个启动问题
- Ubuntu14.04开发环境搭建
- JNI高阶知识总结
- mysql字符串类型截断测试
- php实现非阻塞