There are a total of n courses you have to take, labeled from 0
to n-1
.html
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]
git
Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?github
Example 1:express
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:數據結構
這道課程清單的問題對於咱們學生來講應該不陌生,由於咱們在選課的時候常常會遇到想選某一門課程,發現選它以前必須先上了哪些課程,這道題給了不少提示,第一條就告訴咱們了這道題的本質就是在有向圖中檢測環。 LeetCode 中關於圖的題不多,有向圖的僅此一道,還有一道關於無向圖的題是 Clone Graph。我的認爲圖這種數據結構相比於樹啊,鏈表啊什麼的要更爲複雜一些,尤爲是有向圖,很麻煩。第二條提示是在講如何來表示一個有向圖,能夠用邊來表示,邊是由兩個端點組成的,用兩個點來表示邊。第三第四條提示揭示了此題有兩種解法,DFS 和 BFS 均可以解此題。咱們先來看 BFS 的解法,咱們定義二維數組 graph 來表示這個有向圖,一維數組 in 來表示每一個頂點的入度。咱們開始先根據輸入來創建這個有向圖,並將入度數組也初始化好。而後咱們定義一個 queue 變量,將全部入度爲0的點放入隊列中,而後開始遍歷隊列,從 graph 裏遍歷其鏈接的點,每到達一個新節點,將其入度減一,若是此時該點入度爲0,則放入隊列末尾。直到遍歷完隊列中全部的值,若此時還有節點的入度不爲0,則說明環存在,返回 false,反之則返回 true。代碼以下:app
解法一:ide
class Solution { public: bool canFinish(int numCourses, vector<vector<int>>& prerequisites) { vector<vector<int>> graph(numCourses, vector<int>()); vector<int> in(numCourses); for (auto a : prerequisites) { graph[a[1]].push_back(a[0]); ++in[a[0]]; } queue<int> q; for (int i = 0; i < numCourses; ++i) { if (in[i] == 0) q.push(i); } while (!q.empty()) { int t = q.front(); q.pop(); for (auto a : graph[t]) { --in[a]; if (in[a] == 0) q.push(a); } } for (int i = 0; i < numCourses; ++i) { if (in[i] != 0) return false; } return true; } };
下面咱們來看 DFS 的解法,也須要創建有向圖,仍是用二維數組來創建,和 BFS 不一樣的是,咱們像如今須要一個一維數組 visit 來記錄訪問狀態,這裏有三種狀態,0表示還未訪問過,1表示已經訪問了,-1 表示有衝突。大致思路是,先創建好有向圖,而後從第一個門課開始,找其可構成哪門課,暫時將當前課程標記爲已訪問,而後對新獲得的課程調用 DFS 遞歸,直到出現新的課程已經訪問過了,則返回 false,沒有衝突的話返回 true,而後把標記爲已訪問的課程改成未訪問。代碼以下:post
解法二:ui
class Solution { public: bool canFinish(int numCourses, vector<vector<int>>& prerequisites) { vector<vector<int>> graph(numCourses, vector<int>()); vector<int> visit(numCourses); for (auto a : prerequisites) { graph[a[1]].push_back(a[0]); } for (int i = 0; i < numCourses; ++i) { if (!canFinishDFS(graph, visit, i)) return false; } return true; } bool canFinishDFS(vector<vector<int>>& graph, vector<int>& visit, int i) { if (visit[i] == -1) return false; if (visit[i] == 1) return true; visit[i] = -1; for (auto a : graph[i]) { if (!canFinishDFS(graph, visit, a)) return false; } visit[i] = 1; return true; } };
Github 同步地址:
https://github.com/grandyang/leetcode/issues/207
相似題目:
參考資料:
https://leetcode.com/problems/course-schedule/
https://leetcode.com/problems/course-schedule/discuss/58524/Java-DFS-and-BFS-solution
https://leetcode.com/problems/course-schedule/discuss/58516/Easy-BFS-Topological-sort-Java