leetcode207. 課程表

現在你總共有 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 完成。

拓撲排序,就是判斷構造的圖是否爲有向無環圖。先構建節點入度list和節點鄰接表,然後對入度爲0的節點依次去掉,並將它們的鄰接節點入度減去一,最後看是不是所有節點都變爲入度爲0了:

class Solution:
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        # 拓撲排序,看構造的圖是否爲有向無環圖
        nodes = [0 for _ in range(numCourses)]  # 節點入度
        node_next = [set() for _ in range(numCourses)]  # 節點鄰接表
        for next, node in prerequisites:
            nodes[next] += 1
            node_next[node].add(next)
        queue, count = [], 0  # 入度爲0入隊,記錄入隊個數
        for i in range(len(nodes)):
            if nodes[i] == 0:
                queue.append(i)
        while queue:
            node = queue.pop(0)
            count += 1
            for next in node_next[node]:
                nodes[next] -= 1
                if nodes[next] == 0:
                    queue.append(next)
        return count == numCourses  # 看是不是所有節點都入隊了

最後看nodes也行:

class Solution:
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        # 拓撲排序,看構造的圖是否爲有向無環圖
        nodes = [0 for _ in range(numCourses)]  # 節點入度
        node_next = [set() for _ in range(numCourses)]  # 節點鄰接表
        for next, node in prerequisites:
            nodes[next] += 1
            node_next[node].add(next)
        queue = []  # 入度爲0入隊
        for i in range(len(nodes)):
            if nodes[i] == 0:
                queue.append(i)
        while queue:
            node = queue.pop(0)
            for next in node_next[node]:
                nodes[next] -= 1
                if nodes[next] == 0:
                    queue.append(next)
        return sum(nodes) == 0  # 看是不是所有節點都入隊了
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章