mirror of
https://github.com/ShusenTang/LeetCode.git
synced 2024-09-02 14:20:01 +00:00
Create 207. Course Schedule.md
This commit is contained in:
parent
ce71dbe575
commit
8abc187930
95
solutions/207. Course Schedule.md
Normal file
95
solutions/207. Course Schedule.md
Normal file
@ -0,0 +1,95 @@
|
||||
# [207. Course Schedule](https://leetcode.com/problems/course-schedule/)
|
||||
# 思路
|
||||
仔细分析题目可知这道题的本质就是在有向图中检测环。而在有向图中检测环又可以看作是拓扑排序(不懂拓扑排序的童鞋可[参考此处](https://www.jianshu.com/p/b59db381561a))的应用.
|
||||
拓扑排序又有两种基本思路: BFS和DFS.
|
||||
|
||||
## BFS
|
||||
BFS对有向无环图(DAG, Directed Acyclic Graph)进行拓扑排序的基本思路是:
|
||||
1. 从DAG中选择一个 没有前驱(即入度为0)的顶点并输出;
|
||||
2. 从DAG中删除该顶点和所有以它为起点的有向边;
|
||||
3. 重复 1 和 2 直到当前的 DAG 图为空。
|
||||
|
||||
稍加改动即可判断有向图中是否存在环:
|
||||
1. 先将所有入度(in degree)为0的顶点入栈(或队列);
|
||||
2. 从栈顶取出一个元素并用count自加计数, 将所有以其为起点的边的终点的入度减1, 此时若该终点入度为0则入栈;
|
||||
3. 栈非空时, 重复2;
|
||||
4. 最后判断count是否等于图的顶点数, 若不相等则说明有环.
|
||||
|
||||
为了方便找到以某个顶点为起点的所有边, 我们首先需要建一个二维数组G记录所有边, G[i]记录着以顶点i为起点的所有边的终点. DFS同.
|
||||
|
||||
**时间复杂度分析:**
|
||||
设图有n个顶点,e条边,在拓扑排序的过程中,搜索入度为零的顶点所需的时间是O(n)。
|
||||
在正常情况下,每个顶点进一次栈,出一次栈,所需时间O(n)。每个顶点入度减1的运算共执行了e次(若图基于邻接表)。所以总的时间复杂为O(n+e)。
|
||||
|
||||
## DFS
|
||||
和常见的DFS一样, 我们需要一个一维数组 visited 来记录访问状态,但这里有三种状态:
|
||||
* 0 表示还未访问过, 需要进一步调用递归函数;
|
||||
* 1 表示已经访问了, 直接返回true即可;
|
||||
* -1 表示正在访问, 表示遇到了两次, 有环, 返回false。
|
||||
|
||||
时间复杂度同BFS.
|
||||
|
||||
|
||||
# C++
|
||||
## BFS
|
||||
``` C++
|
||||
class Solution {
|
||||
public:
|
||||
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
|
||||
int arc_num = prerequisites.size();
|
||||
stack<int>stk;
|
||||
vector<int>in_degree(numCourses, 0);
|
||||
vector<vector<int>>G(numCourses, vector<int>{});
|
||||
|
||||
for(auto &arc : prerequisites){ // 建图
|
||||
in_degree[arc[0]]++;
|
||||
G[arc[1]].push_back(arc[0]);
|
||||
}
|
||||
|
||||
for(int i = 0; i < numCourses; i++) // 先将所有入度为0的顶点入栈
|
||||
if(!in_degree[i]) stk.push(i);
|
||||
|
||||
int count = 0;
|
||||
while(!stk.empty()){
|
||||
int course = stk.top(); stk.pop();
|
||||
count++;
|
||||
for(int c: G[course]){ // 所有以course为起点的边的终点
|
||||
if(!(--in_degree[c])) stk.push(c);
|
||||
}
|
||||
}
|
||||
return count == numCourses;
|
||||
}
|
||||
};
|
||||
```
|
||||
## DFS
|
||||
``` C++
|
||||
class Solution {
|
||||
private:
|
||||
bool DFS(vector<vector<int>>&G, vector<int>& visited, int i) {
|
||||
if (visited[i] == -1) return false;
|
||||
if (visited[i] == 1) return true;
|
||||
visited[i] = -1;
|
||||
for (auto a : G[i]) {
|
||||
if (!DFS(G, visited, a)) return false;
|
||||
}
|
||||
visited[i] = 1;
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
|
||||
vector<vector<int>> G(numCourses, vector<int>());
|
||||
vector<int> visited(numCourses, 0);
|
||||
|
||||
for (auto &arc : prerequisites) {
|
||||
G[arc[1]].push_back(arc[0]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < numCourses; ++i)
|
||||
if (!DFS(G, visited, i)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user