Leetcode 207. Course Schedule
题目
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?
Example 1:
Input: 2, [[1,0]]
Output: true
Explanation: There are a total of 2 courses to take.
To take course 1 you should have finished course 0. So it is possible.
Example 2:
Input: 2, [[1,0],[0,1]]
Output: false
Explanation: 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.
Solution 1
简单的DFS
42 / 42 test cases passed.
Status: Accepted
Runtime: 40 ms
Your runtime beats 13.83 % of cpp submissions.
class Solution {
public:
bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
vector< vector<int> > edges(numCourses);
for (int i = 0; i < prerequisites.size(); i++) {
edges[prerequisites[i].first].push_back(prerequisites[i].second);
}
vector<bool> visited(numCourses, false);
for (int i = 0; i < numCourses; i++) {
if (!dfs(i, visited, edges, numCourses)) return false;
}
return true;
}
bool dfs(int course, vector<bool>& visited, vector< vector<int> >& edges, int numCourses) {
if (visited[course]) return false;
else visited[course] = true;
for (int i = 0; i < edges[course].size(); i++) {
if (!dfs(edges[course][i], visited, edges, numCourses)) {
return false;
}
}
visited[course] = false;
return true;
}
};
分析
其实没什么好写的,就是完成了一个DFS……
Solution 2
DFS优化
42 / 42 test cases passed.
Status: Accepted
Runtime: 8 ms
Your runtime beats 99.28 % of cpp submissions.
class Solution {
public:
vector< vector<int> > edges;
vector<bool> visited;
int numCourses;
bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
this->numCourses = numCourses;
edges.resize(numCourses);
visited.assign(numCourses, false);
for (int i = 0; i < prerequisites.size(); i++) {
edges[prerequisites[i].first].push_back(prerequisites[i].second);
}
vector<int> path(numCourses, false);
for (int i = 0; i < numCourses; i++) {
if ( !visited[i] && !dfs(i, path) ) return false;
}
return true;
}
bool dfs(int course, vector<int>& path) {
if (visited[course]) return true;
visited[course] = true;
path[course] = true;
for (int i = 0; i < edges[course].size(); i++) {
if ( path[edges[course][i]] || !dfs(edges[course][i], path) ) {
return false;
}
}
path[course] = false;
return true;
}
};
分析
感觉从这个解里学到了不少,本来我的解法里,visited
就是path
,会在dfs
退出时置回初值。在这个解中,将visited
和path
分开考虑。visited
不会恢复,同时可以发现,每次dfs
都会遍历每个节点的所有后继情况,因此在第一次dfs
遍历过某个节点node[i]
的情况结束后,重新从node[i]
开始是毫无必要的。因此此解法节省了时间。