【LeetCode】210. 課程表 II 結題報告 (C++)
阿新 • • 發佈:2019-02-01
題目描述:
現在你總共有 n 門課需要選,記為 0 到 n-1。
在選修某些課程之前需要一些先修課程。 例如,想要學習課程 0 ,你需要先完成課程 1 ,我們用一個匹配來表示他們: [0,1]
給定課程總量以及它們的先決條件,返回你為了學完所有課程所安排的學習順序。
可能會有多個正確的順序,你只要返回一種就可以了。如果不可能完成所有課程,返回一個空陣列。
示例 1:
輸入: 2, [[1,0]]
輸出: [0,1]
解釋: 總共有 2 門課程。要學習課程 1,你需要先完成課程 0。因此,正確的課程順序為 [0,1] 。
示例 2:
輸入: 4, [[1,0],[2,0],[3,1],[3,2]]
輸出: [0,1,2,3] or [0,2,1,3]
解釋: 總共有 4 門課程。要學習課程 3,你應該先完成課程 1 和課程 2。並且課程 1 和課程 2 都應該排在課程 0 之後。
因此,一個正確的課程順序是 [0,1,2,3] 。另一個正確的排序是 [0,2,1,3] 。
說明:
輸入的先決條件是由邊緣列表表示的圖形,而不是鄰接矩陣。詳情請參見圖的表示法。
你可以假定輸入的先決條件中沒有重複的邊。
提示:
這個問題相當於查詢一個迴圈是否存在於有向圖中。如果存在迴圈,則不存在拓撲排序,因此不可能選取所有課程進行學習。
通過 DFS 進行拓撲排序 - 一個關於Coursera的精彩視訊教程(21分鐘),介紹拓撲排序的基本概念。
拓撲排序也可以通過 BFS 完成。
解題方案:
與上一題207 課程表的思路是相同的:
class Solution { public: vector<int> findOrder(int numCourses, vector<pair<int, int>>& prerequisites) { vector<int> heads(numCourses, -1), degree(numCourses, 0), points, args; pair<int, int> p; vector<int> ans; int from, to, count = 0, len = prerequisites.size(); /* 構造有向圖,鄰接表 */ for (int i = 0; i < len; ++i) { p = prerequisites[i]; from = p.second; to = p.first; ++degree[to]; args.push_back(heads[from]); points.push_back(to); heads[from] = count++; } /* bfs拓撲排序,依次移除入度為0的點 */ queue<int> q; for (int i = 0; i < numCourses; ++i) if (degree[i] == 0){ q.push(i); ans.push_back(i); } while (!q.empty()) { from = q.front(); q.pop(); to = heads[from]; while (to != -1) { if(--degree[points[to]] == 0){ q.push(points[to]); ans.push_back(points[to]); } to = args[to]; } } /* 判定是否所有的點入度都為0,若是則不存在環,否則存在環 */ for (int i = 0; i < numCourses; ++i) if (degree[i] > 0) return vector<int>(); return ans; } };