Medium草稿★★★★★O(V + E) 時間 · O(V + E) 空間
GraphTopological SortBFSDFS
Patterns📋 拓撲排序🌊 廣度優先 BFS🕸️ 圖遍歷・連通分量
尚未複習過

解法已隱藏 — 先讀題目敘述、自己想想看,再點上方按鈕揭曉。

207Course ScheduleGraphsMediumGraphs

共有 numCourses 門課(編號 0numCourses - 1),prerequisites[i] = [a, b] 表示修課 a 前需先修 b。判斷是否能修完所有課程(即有向圖中是否存在環)。

Example:

Input: numCourses = 2, prerequisites = [[1,0]] Output: true

Intuition

TIP

課程依賴是有向圖,能修完所有課 = 圖中無環 = 可以進行拓撲排序。

Approaches

1. DFS (cycle detection) — O(V + E) / O(V + E)
  • Idea: 用三色標記法(未訪問/處理中/已完成)偵測有向圖中的環
  • Time: O(V + E)
  • Space: O(V + E)
class Solution {
    fun canFinish(numCourses: Int, prerequisites: Array<IntArray>): Boolean {
        val graph = Array(numCourses) { mutableListOf<Int>() }
        for ((a, b) in prerequisites) graph[b].add(a)

        val state = IntArray(numCourses) // 0: unvisited, 1: visiting, 2: visited

        fun dfs(node: Int): Boolean {
            if (state[node] == 1) return false // cycle
            if (state[node] == 2) return true
            state[node] = 1
            for (next in graph[node]) {
                if (!dfs(next)) return false
            }
            state[node] = 2
            return true
        }

        for (i in 0 until numCourses) {
            if (!dfs(i)) return false
        }
        return true
    }
}
⭐ 2. BFS (Kahn's Algorithm — topological sort) — O(V + E) / O(V + E)
  • Idea: 計算每個節點的入度,從入度為 0 的節點開始 BFS,逐步移除邊。若最終所有節點都被處理,則無環。
  • Time: O(V + E)
  • Space: O(V + E)
class Solution {
    fun canFinish(numCourses: Int, prerequisites: Array<IntArray>): Boolean {
        val graph = Array(numCourses) { mutableListOf<Int>() }
        val inDegree = IntArray(numCourses)

        for ((a, b) in prerequisites) {
            graph[b].add(a)
            inDegree[a]++
        }

        val queue: ArrayDeque<Int> = ArrayDeque()
        for (i in 0 until numCourses) {
            if (inDegree[i] == 0) queue.add(i)
        }

        var count = 0
        while (queue.isNotEmpty()) {
            val cur = queue.removeFirst()
            count++
            for (next in graph[cur]) {
                inDegree[next]--
                if (inDegree[next] == 0) queue.add(next)
            }
        }

        return count == numCourses
    }
}

🔑 Takeaways

Ladders 看全部 →

🧭

課程表 / 拓樸排序

建圖 → 判環 → 輸出順序。

  1. 1
  2. 2#210Course Schedule IIMedium輸出一組合法修課順序
  3. 3#269Alien DictionaryHard從字典序反推字母順序(建圖 + 拓樸)