【LeetCode】207. 課程表 結題報告 (C++)
阿新 • • 發佈:2018-11-21
原題地址:https://leetcode-cn.com/problems/course-schedule/description/
題目描述:
現在你總共有 n 門課需要選,記為 0 到 n-1。
在選修某些課程之前需要一些先修課程。 例如,想要學習課程 0 ,你需要先完成課程 1 ,我們用一個匹配來表示他們: [0,1]
給定課程總量以及它們的先決條件,判斷是否可能完成所有課程的學習?
示例 1:
輸入: 2, [[1,0]]
輸出: true
解釋: 總共有 2 門課程。學習課程 1 之前,你需要完成課程 0。所以這是可能的。
示例 2:
輸入: 2, [[1,0],[0,1]]
輸出: false
解釋: 總共有 2 門課程。學習課程 1 之前,你需要先完成課程 0;並且學習課程 0 之前,你還應先完成課程 1。這是不可能的。
說明:
輸入的先決條件是由邊緣列表表示的圖形,而不是鄰接矩陣。詳情請參見圖的表示法。
你可以假定輸入的先決條件中沒有重複的邊。
提示:
這個問題相當於查詢一個迴圈是否存在於有向圖中。如果存在迴圈,則不存在拓撲排序,因此不可能選取所有課程進行學習。
通過 DFS 進行拓撲排序 - 一個關於Coursera的精彩視訊教程(21分鐘),介紹拓撲排序的基本概念。
拓撲排序也可以通過 BFS 完成。
解題方案:
這道題涉及了很多話題:dfs、bfs、圖以及拓撲排序。解題思路如下:
- 首先構造有向圖,構造圖有三種方式:關聯矩陣,鄰接矩陣和鄰接表。這裡採用的是鄰接表,因為要採取很多的插入操作。
- 接著,採用bfs進行拓撲排序,學習拓撲排序的方法,每次篩選時,刪除度為0的節點。
- 最後是判定,若存在度不為0的節點,則說明存在著環。
程式碼:
class Solution { public: bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) { vector<int> heads(numCourses, -1), degree(numCourses, 0), points, args; pair<int, int> p; 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); while (!q.empty()) { from = q.front(); q.pop(); to = heads[from]; while (to != -1) { if(--degree[points[to]] == 0) q.push(points[to]); to = args[to]; } } /* 判定是否所有的點入度都為0,若是則不存在環,否則存在環 */ for (int i = 0; i < numCourses; ++i) if (degree[i] > 0) return false; return true; } };
今天是10.24,程式設計師日??說實話,真的沒有感覺,對程式設計師沒啥認同感。。。
沒想到大家這麼重視,CSDN送一枚徽章還是美滋滋的,哈哈哈。。。