zoukankan      html  css  js  c++  java
  • [LeeCode] 207. Course Schedule Java

    题目:

    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.

    题意及分析:课程之间有依赖关系,问是否能安排课程表。从图论的角度来看就是:有向图是否存在环,存在就false,否则就返回true。最开始我想到的是暴力求解,直接对每个点查找是否能返回到该点,若有则直接返回false,最后超时。判断一个有向图是否有环,可以使用拓扑排序:

    一个 DAG 图,那么如何写出它的拓扑排序呢?这里说一种比较常用的方法:

    1. 从 DAG 图中选择一个 没有前驱(即入度为0)的顶点并输出。
    2. 从图中删除该顶点和所有以它为起点的有向边。
    3. 重复 1 和 2 直到当前的 DAG 图为空或当前图中不存在无前驱的顶点为止。后一种情况说明有向图中必然存在环。

    超时代码:

    public class Solution {
        public boolean canFinish(int numCourses, int[][] prerequisites) {
            int row = prerequisites.length;
            if(row==0) return true;
            HashMap<Integer,List<Integer>> hashMap = new HashMap<>();       //记录每个出发点及其能到达的点,list为学习该门课程需要学习的先序课程
            for(int i=0;i<row;i++){
                int[] edge = prerequisites[i];
                int begin = edge[0];        //课程
                int end = edge[1];          //需要的先序课程
                if(hashMap.containsKey(begin)){
                    hashMap.get(begin).add(end);
                }else{
                    List<Integer> temp = new ArrayList<>();
                    temp.add(end);
                    hashMap.put(begin,temp);
                }
            }
    
            Queue<Integer> tempQueue = new LinkedList<>();      //用来进行宽度遍历,需要弹出的
    
            Iterator iter = hashMap.entrySet().iterator();
            while(iter.hasNext()){
                Queue<Integer> queue = new LinkedList<>();      //记录从该点开始被遍历过的点
                Map.Entry entry = (Map.Entry) iter.next();
                int key = (Integer) entry.getKey();
                tempQueue.add(key);         //该队列用来对该点就行宽度遍历查找
                while(!tempQueue.isEmpty()){
                    int num = tempQueue.poll();
                    List<Integer> neighbor = hashMap.get(num);   //该点能到达的点
                    if(!queue.contains(num)){       //该点未被遍历过
                        queue.add(num);
                        if(neighbor!=null){     //若有该点能到达的点
                            for(int i=0;i<neighbor.size();i++){
                                if(key==(neighbor.get(i))) {     //包含循环,又回到起始点
                                    return false;
                                }else {
    //                                queue.add(neighbor.get(i));
                                    tempQueue.add(neighbor.get(i));
                                }
                            }
                        }
                    }
                }
    
            }
            return true;
        }
    }

     拓扑排序代码:

    public class Solution {
        public boolean canFinish(int numCourses, int[][] prerequisites) {
            int[] map = new int[numCourses];        //记录每个点的入度
    
            for(int i=0;i<prerequisites.length;i++){      //计算入度
                map[prerequisites[i][1]]++;
            }
    
            Queue<Integer> queue = new LinkedList<>();      //保存没有前驱的点,即入度为0的点
            for(int i=0;i<map.length;i++){
                if(map[i]==0) queue.add(i);
            }
    
            int count = queue.size();     //用来记录被删除的点的个数,若和课程数相等则可以排出课程
            while (!queue.isEmpty()){
                int key = queue.poll();     //删除的课程,并将该课程的所能达到的所有点的入度减1
                for(int i=0;i<prerequisites.length;i++){
                    if(key==prerequisites[i][0]){
                        int l = prerequisites[i][1];
                        map[l]--;       //入度减1
                        if(map[l]==0){  //入度为0,添加进queue
                            queue.add(l);
                            count++;
                        }
                    }
                }
            }
            return count==numCourses;
        }
    }
  • 相关阅读:
    挑战程序设计竞赛 2.1 最基础的“穷竭搜索”
    HDU 5145 NPY and girls(莫队算法+乘法逆元)
    BZOJ 4300 绝世好题(位运算)
    HDU 5724 Chess(博弈论)
    BZOJ 1177 [Apio2009]Oil(递推)
    Codeforces 706D Vasiliy's Multiset(可持久化字典树)
    HDU 3374 String Problem (KMP+最小最大表示)
    POJ 2758 Checking the Text(Hash+二分答案)
    HDU 5782 Cycle(KMP+Hash)
    POJ 3450 Corporate Identity(KMP)
  • 原文地址:https://www.cnblogs.com/271934Liao/p/7243541.html
Copyright © 2011-2022 走看看