1. 程式人生 > 實用技巧 >【LeetCode】207. 課程表

【LeetCode】207. 課程表

題目:

你這個學期必須選修 numCourse 門課程,記為 0 到 numCourse-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。這是不可能的。

提示:

輸入的先決條件是由 邊緣列表 表示的圖形,而不是 鄰接矩陣 。詳情請參見圖的表示法。

你可以假定輸入的先決條件中沒有重複的邊。

1 <= numCourses <= 10^5

解題思路:

這個題目可以轉化成圖的問題來解,需要引申一個圖裡的定義:拓撲排序。

給定一個包含 n 個節點的有向圖 G,我們給出它的節點編號的一種排列,如果滿足:

對於圖 G 中的任意一條有向邊 (u, v),u 在排列中都出現在 v 的前面。

我們可以將深度優先搜尋的流程與拓撲排序的求解聯絡起來,用一個棧來儲存所有已經搜尋完成的節點。

對於一個節點 u,如果它的所有相鄰節點都已經搜尋完成,那麼在搜尋回溯到 u 的時候,u 本身也會變成一個已經搜尋完成的節點。這裡的「相鄰節點」指的是從 u 出發通過一條有向邊可以到達的所有節點。

假設我們當前搜尋到了節點 u,如果它的所有相鄰節點都已經搜尋完成,那麼這些節點都已經在棧中了,此時我們就可以把 u 入棧。可以發現,如果我們從棧頂往棧底的順序看,由於 u 處於棧頂的位置,那麼 u 出現在所有 u 的相鄰節點的前面。因此對於 u 這個節點而言,它是滿足拓撲排序的要求的。

這樣以來,我們對圖進行一遍深度優先搜尋。當每個節點進行回溯的時候,我們把該節點放入棧中。最終從棧頂到棧底的序列就是一種拓撲排序。

程式碼:

 1 class Solution {
 2  
 3     /**
 4      * @param Integer $numCourses
 5      * @param Integer[][] $prerequisites
6 * @return Boolean 7 */ 8 function canFinish($numCourses, $prerequisites) { 9 $adj = array_fill(0,$numCourses,[]); // 鄰接關係表 10 foreach($prerequisites as $p){ 11 $adj[$p[1]][] = $p[0]; // 記錄每個點的可達節點集合 12 } 13 $visited = array_fill(0,$numCourses,0); // 建立訪問記錄陣列,0代表未訪問,1代表正在被當前dfs佔用,2代表已訪問未佔用 14 for($i=0;$i<$numCourses;$i++){ 15 if(!$this->dfs($i,$adj,$visited)) return false; // 說明存在環,課程任務不能完成。 16 } 17 return true; 18 } 19 20 function dfs($i,$adj,&$visited){ 21 if($visited[$i]==1) return false; // 1代表正在被當前dfs佔用,說明遇到了環。 22 if($visited[$i]==2) return true; // 2代表已訪問未佔用 23 $visited[$i] = 1; // 開始佔用訪問資源 24 foreach($adj[$i] as $node){ 25 if(!$this->dfs($node,$adj,$visited)) return false; 26 } 27 $visited[$i] = 2; // 解除佔用,標記為已訪問未佔用 28 return true; 29 } 30 }

  

說明:

本題題解參考LeetCode官方題解:https://leetcode-cn.com/problems/course-schedule/solution/ke-cheng-biao-by-leetcode-solution/

程式碼參考:https://leetcode-cn.com/problems/course-schedule/solution/zhe-ti-bu-da-hui-by-wu-chen-ge/