210. Course Schedule II

Posted on Jun 2, 2025

Solution

  • 這題是 Leetcode 207 的進化版本,除了要確認課程能不能修完,還要給出完成課程的順序,只要是能順利完成的順序都可以。因此做法透過我的 207. Course Schedule 來修改的,可以參考這題的程式碼。
  • 這題的做法一樣也使用 DFS,不過在 DFS 的過程中除了把每個課程跑過一遍之後,還要記錄哪些課程可以先修。因此只要能 return truenum 都是課可以修掉的,只要遇到就加到 courseOrdercourseOrder 是一個 LinkedHashSet,除了可以當一般的 Set 使用(檢查是否有某元素,排除重複元素)之外,他也會留著 add() 元素加入的順序,可以當作 List 和 Set 的混合版。
  • 把每一個數字都跑過一次 DFS,過程中就會建立 courseOrder 的順序,如果當中有迴圈而沒辦法修課完畢,就回傳一個空的 Array,成功的話就會在最後 return courseOrder
  • Time: O(V + E), Space: O(V)

Implementation

class Solution {
    fun findOrder(numCourses: Int, prerequisites: Array<IntArray>): IntArray {
        val preMap = Array(numCourses) { mutableListOf<Int>() }
        for (item in prerequisites) {
            val (course, prerequisite) = item[0] to item[1]
            preMap[course].add(prerequisite)
        }

        val courseOrder = linkedSetOf<Int>()
        val visited = mutableSetOf<Int>()
        fun dfs(num: Int): Boolean {
            if (num in visited) return false
            if (preMap[num].isEmpty()) {
                courseOrder.add(num)
                return true
            }
            
            visited.add(num)
            for (pre in preMap[num]) {
                if (!dfs(pre)) return false
            }
            visited.remove(num)

            preMap[num].clear()
            courseOrder.add(num)
            return true
        }

        for (course in 0 until numCourses) {
            if (!dfs(course)) return intArrayOf()
        }

        return courseOrder.toIntArray()
    }
}