Leetcode207 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?
題意
共有n門課程需要學習,課程編號從0至n-1。
有些課程有先修要求,比如必須先修課程1後修課程0,用[0, 1]表示。
給出總課程數和先後修要求對,判斷是否有可能完成所有課程。
分析
很顯然,這是一個有向無環圖的判斷問題。只要所有課程中出現了環,就不可能修滿所有課程。有向無環圖的判斷可採用dfs或bfs,至於生成圖的形式可以是鄰接矩陣,也可以是鄰接表。爲了減小時間複雜度,本題考慮採用鄰接表的方法。
注意
如果採用鄰接矩陣可能會導致時間超限。另外可以採用bfs的方法求是否有環。基本思路就是將入度爲0的課程放入隊列。直到所有課程都被完成或發現一個環。
基本步驟
1. 將每個先後修要求對導入鄰接表中。
2. 將使用dfs判斷是否無環:
2.1 用isVisited記錄各個課程是否被訪問過;
2.2 用onStack記錄一條路徑上的課程,判斷是否有環;
2.3 有環返回true,無環繼續;
3. 如有環主函數返回false,否則返回true。
AC代碼
class Solution {
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
if (!prerequisites.size()) return true;
vector<vector<int>> map(numCourses, vector<int>());
for (int i = 0; i < prerequisites.size(); ++i) {
map[prerequisites[i][0]].push_back(prerequisites[i][1]);
}
vector<bool> isVisited(numCourses, false);
for (int i = 0; i < numCourses; ++i) {
if (!isVisited[i]) {
vector<bool> onStack(numCourses, false);
if (hasCycle(map, i, isVisited, onStack))
return false;
}
}
return true;
}
bool hasCycle(vector<vector<int>> &map, int i, vector<bool> &isVisited, vector<bool> &onStack) {
isVisited[i] = true;
onStack[i] = true;
for (int k : map[i]) {
if (onStack[k])
return true;
else
if (hasCycle(map, k, isVisited, onStack))
return true;
}
onStack[i] = false;
return false;
}
};
如代碼或分析有誤,請批評指正,謝謝。