LeetCode 207. 課程表(Medium)

Aiclin發表於2020-12-28

在這裡插入圖片描述
【題目連結】

題解

  1. 課程表(拓撲排序:入度表BFS法 / DFS法,清晰圖解)

思路

在這裡插入圖片描述
在這裡插入圖片描述

程式碼

from collections import deque
class Solution:
    ### 1227 BFS(40 ms,15.7 MB)
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        queue = deque()

        # 初始化入度表全0,鄰接表全為空
        indegrees = [0 for _ in range(numCourses)]
        adjacency = [[] for _ in range(numCourses)]

        # 填充入度表和鄰接表
        for cur, pre in prerequisites:
            indegrees[cur] += 1        # 累計每門課的前置課有多少門(即每個節點的入度)
            adjacency[pre].append(cur) # 累計當前課程是多少門課的前置課

        # 將所有沒有前置課的節點入隊(即入度為0的起始節點入隊)
        for i in range(len(indegrees)):
            if not indegrees[i]: queue.append(i)

        # 開始TopSort,當queue非空時,進行迴圈
        while queue:
            pre = queue.popleft() # 前置課程出隊
            numCourses -= 1       # 待排序課程減一

            # 遍歷當前前置課的所有後置課
            for cur in adjacency[pre]:
                # 後置課的入度少一,若入度為0,則此後置課作為新的前置課入隊
                indegrees[cur] -= 1
                if not indegrees[cur]: queue.append(cur)
        
        return not numCourses # 判斷全部課程是否排完

    ### 1227 DFS(44 ms,17.4 MB)
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        # 判斷
        def dfs(i, adjacency, flag):
            if flag[i] == -1: return True # flag[i] == -1表示表示此節點已被訪問
            if flag[i] == 1: return False # flag[i] == 1表示二次訪問此節點,即出現環,返回False

            flag[i] = 1 # 首次訪問該節點時令flag[i] = 1表示此節點已經訪問

            # 遍歷該節點的所有後置節點
            for j in adjacency[i]:
                # 若出現二次訪問某節點,即出現環,返回False
                if not dfs(j, adjacency, flag): return False
            
            flag[i] = -1 # 若該節點的所有後置節點均滿足條件,則置此節點的flag為-1,並返回True表示可行
            return True
        
        # 初始化鄰接表全為空,flag全為0表示還未訪問
        adjacency = [[] for _  in range(numCourses)]
        flag = [0 for _ in range(numCourses)]

        # 填充鄰接表(即每門前置課有多少門後置課)
        for cur, pre in prerequisites:
            adjacency[pre].append(cur)

        # 對於每一門課,若其後置課出現了環,則返回False
        for i in range(numCourses):
            if not dfs(i, adjacency, flag): return False
        
        return True # 對於每一門課,若其後置課都滿足條件,則返回True

相關文章