1. 程式人生 > >LeetCode刷題MEDIM篇Course Schedule II

LeetCode刷題MEDIM篇Course Schedule II

題目

There are a total of n courses you have to take, labeled from 0 to n-1.

Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]

Given the total number of courses and a list of prerequisite pairs

, return the ordering of courses you should take to finish all courses.

There may be multiple correct orders, you just need to return one of them. If it is impossible to finish all courses, return an empty array.

Example 1:

Input: 2, [[1,0]] 
Output: [0,1]
Explanation: There are a total of 2 courses to take. To take course 1 you should have finished   
             course 0. So the correct course order is [0,1] .

Example 2:

Input: 4, [[1,0],[2,0],[3,1],[3,2]]
Output: [0,1,2,3] or [0,2,1,3]
Explanation: There are a total of 4 courses to take. To take course 3 you should have finished both     
             courses 1 and 2. Both courses 1 and 2 should be taken after you finished course 0. 
             So one correct course order is [0,1,2,3]
. Another correct ordering is [0,2,1,3] .

Note:

  1. The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented.
  2. You may assume that there are no duplicate edges in the input prerequisites.

十分鐘嘗試

之前做過I的題目,是判斷是否有迴圈依賴,是否能完成,本質就是拓撲排序,判斷是否是一個DAG有向無環圖的問題。

這個題目是需要輸出序列,可以順利完成的序列。我們可以把依賴關係看成一個有向圖,因為可以輸出結果,所以給定的序列一定沒有環。現在的問題是輸出這個序列,那麼我們就用拓撲排序的DFS或者BFS處理。我習慣用BFS處理。先找遍歷,各個節點的入度存入indegree陣列,然後入度為0加入佇列,同時所有子節點入度減去1,如果子節點入度為0,也加入佇列,迴圈直到佇列為空。輸出的序列反序就是所求,add(0,element)就可以,不用單獨排序。

但是發現結果是需要陣列,不是queue,為了不再轉化,所以定義一個數組,在BFS的時候新增元素到陣列,注意從尾部開始。索引index最後重要的作用來判斷是否進行了BFS,是否無環,因為如果有環,無法完全輸出,index最後不會為0,此時輸出int[0].

之前的演算法判斷indegree是否都為0,那是因為需要判斷是否有環,如果有環就不全部為0.這個題目也可以,如果有環返回int[0],如果沒有環,返回result。但是我們這裡用index判斷輸出的數字個數是否是全部,都可以。詳見另外一個題目:

https://blog.csdn.net/hanruikai/article/details/85629425

class Solution {
    public int[] findOrder(int numCourses, int[][] prerequisites) {
        int index=numCourses;
        int[] result=new int[numCourses];
        int[] indegree=new int[numCourses];
        if(numCourses==0){
            return result;
        }
        //計算各個入度
        for(int i=0;i<prerequisites.length;i++){
            indegree[prerequisites[i][1]]++;
        }
        //尋找入度為0的,入queue
        Deque  queue=new LinkedList();
        for(int i=0;i<indegree.length;i++){
            if(indegree[i]==0){
                //第二次寫錯了,應該是i
                 queue.add(i);
            }
        }
        //遍歷佇列如果不為空
        while(!queue.isEmpty()){
            int curr=(Integer)queue.poll();
             result[--index]=curr;
            //處理所有子,所有子入度減去1
            for(int i=0;i<prerequisites.length;i++){
                if(prerequisites[i][0]==curr){
                    indegree[prerequisites[i][1]]--;
                    if(indegree[prerequisites[i][1]]==0){
                        queue.add(prerequisites[i][1]);
                    }
                }
            }
        }
        //如果無環,能輸出,最後index==0,否則輸出一部分或者完全沒有輸出序列
        if(index!=0){
            return new int[0];
        }
        return result;
    }
}