LeetCode : 207. Course Schedule 课程先后顺序规划

试题
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?

Example 1:

Input: 2, [[1,0]]
Output: true
Explanation: There are a total of 2 courses to take.
To take course 1 you should have finished course 0. So it is possible.
Example 2:

Input: 2, [[1,0],[0,1]]
Output: false
Explanation: 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.

代码
有以下思路:
1、对于没有入度出度的节点可以直接完成,对于没有入度的节点也可以直接完成。
2、有入度的节点必须要依赖的节点都完成了,才能够完成。我们可以统计每个节点的依赖完成数量。
3、使用宽度优先,先完成1中节点,然后当2中节点的依赖完成后才能完成。

class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        if(prerequisites.length == 0) return true;
        
        
        HashSet<Integer> start = new HashSet<>();
        HashMap<Integer, ArrayList<Integer>> graph = new HashMap<>();
        Stack<Integer> stack = new Stack<>();
        int[] sum = new int[numCourses];
        
        for(int i = 0; i < numCourses; i++){
            start.add(i);
        }
        for(int[] e : prerequisites){
            sum[e[1]]++;
            if(start.contains(e[1])){
                start.remove(e[1]);
            }
            if(graph.containsKey(e[0])){
                graph.get(e[0]).add(e[1]);
            }else{
                ArrayList<Integer> temp = new ArrayList<>();
                temp.add(e[1]);
                graph.put(e[0], temp);
            }
        }
        
        if(start.size() == 0){
            return false;
        }
        for(int s : start){
            stack.push(s);
        }
        int count = 0;
        
        while(!stack.isEmpty()){
            int size = stack.size();
            for(int i = 0; i < size; i++){
                int cur = stack.pop();
                count++;
                
                if(graph.containsKey(cur)){
                    ArrayList<Integer> nxt = graph.get(cur);
                    for(int n : nxt){
                        sum[n]--;
                        if(sum[n] == 0){
                            stack.push(n);
                        }
                    }   
                }    
            }
        }
        
        if(count == numCourses){
            return true;
        }
        return false;
        
    }
}

另外其实这题有个特点是如果无法完成,那么说明图中存在一个环。所以可快速判断图中是否有环。

class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        if (numCourses == 0 || prerequisites == null || prerequisites.length == 0) return true; // ??
        
        // Index of this list is a course and its values are the dependencies (children)
        List<List<Integer>> courseDependency = new ArrayList<>(numCourses);
        
        for (int i = 0; i < numCourses; i++)
            courseDependency.add(new ArrayList<>());
        
        /*
        create following courseDependency arraylist for each index (course)
            0: [1,2],
            1: [2],
            2: []
        */
        for (int i = 0; i < prerequisites.length; i++) {
            courseDependency.get(prerequisites[i][0]).add(prerequisites[i][1]);
        }

        // use state int array to represent current status of visiting for each node
		// 0: not visited yet, 1: currently visiting (in recursion stack frame), 2: already visited
        int[] state = new int[numCourses];
        
        for (int i = 0; i < numCourses; i++) {
            if (!dfs(i, courseDependency, state)) {
                return false;   // Cycle found
            }
        }
        
        // no cycle found
        return true;
    }
    
    private boolean dfs(int course, List<List<Integer>> courseDependency, int[] state) {
        
        state[course] = 1;  // currently visiting
        
        List<Integer> dependencies = courseDependency.get(course);
        
        for (int children: dependencies) {
            if (state[children] == 1)   // If any children is also being currently visiting, then cycle is detected
                return false;
            
            if (state[children] == 0) { // Not visted yet
                if (!dfs(children, courseDependency, state))
                    return false;
            }
        }
        
        state[course] = 2;  // done visiting
        return true;        // no cycle, backtrack to caller
    }
}
发布了557 篇原创文章 · 获赞 500 · 访问量 153万+

猜你喜欢

转载自blog.csdn.net/qq_16234613/article/details/100668765