207,210. Course Schedule I, II

Course Schedule I

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, is it possible for you to finish all courses?

For example:

2, [[1,0]]

There are a total of 2 courses to take. To take course 1 you should have finished course 0. So it is possible.

2, [[1,0],[0,1]]

There are a total of 2 courses to take. To take course 1 you should have finished course 0, and to take course 0 you should also have finished course 1. So it is impossible.

Note:

The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented.

思路:本題等同於圖裏找circle。 用DFS找circle。爲剪枝,找到circle,直接停止(用個全局變量)。起始把數組轉換成Hashmap便於DFS。

public class Solution {
    public boolean findCircle = false;
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        Map<Integer, List<Integer>> map = new HashMap<>();
        for(int i=0; i<prerequisites.length; i++){
            if(!map.containsKey(prerequisites[i][0])){
                List<Integer> al = new ArrayList<>();
                al.add(prerequisites[i][1]);
                map.put(prerequisites[i][0],al);
            }
            else{
                map.get(prerequisites[i][0]).add(prerequisites[i][1]);
            }
        }
        boolean[] marked = new boolean[numCourses];
        for(int i=0; i<numCourses; i++){
            if(findCircle) break;
            dfs(i,map,marked);
        }
        return !findCircle;
    }
    public void dfs(int n, Map<Integer, List<Integer>> map, boolean[] marked){
        if(marked[n]){
            findCircle=true;
            return;
        }
        if(!map.containsKey(n) || findCircle) return;
        List<Integer> al = map.get(n);
        marked[n]=true;
        for(int i=0; i<al.size(); i++){
            if(findCircle) break;
            dfs(al.get(i), map, marked);
        }
        marked[n]=false;
    }
}

思路2: BFS

先得到每個節點入度的數組in[]和所有入度爲0的節點作爲起始點集,開始BFS遍歷,到一個點將其入度-1,如果入度爲0,將其放到起始點集中,最後如果起始點集中元素個數大於總節點個數,則有圈。

Course Schedule II: Return correct course order

BFS Topology Sort, use in-degree array.

public class Solution {
    public int[] findOrder(int numCourses, int[][] prerequisites) {
        Map<Integer, List<Integer>> forward = new HashMap<>(); 
        int[] in = new int[numCourses];
        ArrayList<Integer> roots = new ArrayList<>();
        int[] result = new int[numCourses];
        int count = numCourses-1;
        //0. convert edge array into hashmap
        for(int i=0; i<prerequisites.length; i++){  
            if(!forward.containsKey(prerequisites[i][0])){  
                List<Integer> al = new ArrayList<>();  
                al.add(prerequisites[i][1]);  
                forward.put(prerequisites[i][0],al);  
            }  
            else{  
                forward.get(prerequisites[i][0]).add(prerequisites[i][1]);  
            }  
            in[prerequisites[i][1]]++;
        }  
        //1. find all root candidats
        for(int i=0; i<numCourses; i++){
            if(in[i]==0) roots.add(i);
        }
        //2. bfs for all roots
        while(!roots.isEmpty()){
            int root = roots.remove(0);
            result[count] = root;
            count--;
            List<Integer> children = forward.get(root);
            while(children!=null && !children.isEmpty()){
                int child = children.remove(0);
                in[child]--;
                if(in[child]==0){
                    roots.add(child);
                    forward.remove(root);
                }
            }
        }
        for(int i=0; i<numCourses; i++){
            if(in[i]>0) return new int[0];
        }
        return result;
    }
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章