1. 程式人生 > 實用技巧 >LeetCode210. 課程表 II

LeetCode210. 課程表 II

這題和LeetCode207. 課程表一樣,都是拓撲排序的模板題,只不過207題只需判斷是否存在拓撲序列,
這題要返回拓撲序列。

只需要在BFS時在一個結果陣列中記錄每個入隊的元素即可,最後判斷陣列大小是否和課程總數量numCourses相同,相同就返回我們記錄的所有元素的入隊順序的陣列res,
不相同就返回空陣列。

關於拓撲排序,可以看一下上面那個連結裡(207題)的步驟,207題搞定了,這題就稍微改一下就可以了。

程式碼如下:

class Solution {
public:
    vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
        vector<vector<int>> g(numCourses);                  //g表示課程關係之間的圖,g[i]陣列存放課程i的所有後繼課程
        vector<int> inDegree(numCourses);                   //inDegree[i]表示課程i的入度(先修課程的數量)
        for(int i = 0; i < prerequisites.size(); ++i) {
            int course1 = prerequisites[i][0], course2 = prerequisites[i][1];      //這題的輸入比較奇怪,prerequisties的第一門課是後繼課程,第二門課才是先修課程,注意一下順序
            g[course2].push_back(course1);                  //course2是course1的先修課程
            ++inDegree[course1];                            //course1的先修課程數量加一
        }
        vector<int> res;                              //存放拓撲序列
        queue<int> q;
        for(int i = 0; i < numCourses; ++i) {            //拓撲排序最開始把所有入度為0的節點入隊
            if(inDegree[i] == 0) {
                q.push(i);
            }
        }
        while(q.size()) {
            int curCourse = q.front();                  //隊頭元素出隊,表示這門課程學完了
            q.pop();
            res.push_back(curCourse);
            for(int i = 0; i < g[curCourse].size(); ++i) {      //這門學習完的課程的所有後繼課程的入度(先修課程數量)可以減一了
                --inDegree[g[curCourse][i]];
                if(inDegree[g[curCourse][i]] == 0) {            //如果入度減一之後為0,則入隊
                    q.push(g[curCourse][i]);
                }
            }
        }
        if(res.size() != numCourses) {             //無法學習完所有課程,返回空陣列
            return {};
        }
        return res;                              //存在一種包含所有課程的拓撲序列,則返回
    }
};