207. Course Schedule

一、题目

  1、审题

  

  2、分析

    给出顶点数、指向当前顶点的前驱顶点,判断当前顶点组成的图是否是一个有向无环图。

 

二、解答

  1、思路:

    方法一、

      采用拓扑排序

      ①、定义数组 matrix[][] 存储从 i 指向 j 的边,curArr[] 存储指向当前顶点的边数。并初始化这两个数组;

      ②、将没有前驱的顶点存入队列中,依次出列;

      ③、将出列的顶点为起始的边依次去除,即将 curArr[i] 值 -1;若 curArr[i] == 0,则 i 入队列;

      ④、最终队列为空时,若总共入队的元素个数与顶点个数相等,则为有向无环图,否则,为有环图。

    public boolean canFinish2(int numCourses, int[][] prerequisites) {
        
        int[][] matrix = new int[numCourses][numCourses];    // 存储边
        int[] curArr = new int[numCourses];            // curArr[m] = n: 有 n 个指针指向 m 
        
        for (int i = 0; i < prerequisites.length; i++) {
            int pre = prerequisites[i][1];
            int cur = prerequisites[i][0];
            
            if(matrix[pre][cur] == 0)
                curArr[cur] = 1;
            matrix[pre][cur] = 1;
        }
        
        Queue<Integer> queue = new LinkedList<>();
        for (int i = 0; i < numCourses; i++) {
            if(curArr[i] == 0)
                queue.offer(i);
        }
        
        int count = 0;
        while(!queue.isEmpty()) {
            count++;
            int course = queue.poll();
            for (int i = 0; i < numCourses; i++) {
                if(matrix[course][i] != 0 && --curArr[i] == 0)
                    queue.offer(i);
            }
        }
        return count == numCourses;
    }

 

  方法二、

    采用 DFS

    ①、首先构造图,用 Map 存储,Key 为顶点,value 为直接前驱顶点;

    ②、往前驱顶点进行深度遍历图中每个顶点,判断是否该顶点重复出现,若是,返回 false;

    ③、遍历完途中的所有顶点,返回 true;

    public boolean canFinish(int numCourses, int[][] prerequisites) {
        if(prerequisites == null)
            return false;
        
        // key: 当前顶点, value: 所有直接前驱顶点
        HashMap<Integer, List<Integer>> grap = new HashMap<>();
        for(int[] curPair: prerequisites) {
            List<Integer> match = grap.get(curPair[0]);
            if(match == null) {
                match = new ArrayList<Integer>();
                match.add(curPair[1]);
                grap.put(curPair[0], match);
            }
            else {
                match.add(curPair[1]);
            }
        }
        
        HashSet<Integer> prevRoots = new HashSet<>();
        for(Integer curRoot: grap.keySet()) {
            boolean[] hasCircle = new boolean[1];
            DFS(prevRoots, curRoot, grap, hasCircle);
            if(hasCircle[0])
                return false;
        }
        return true;
    }
    
    private void DFS(HashSet<Integer> prevRoots, Integer start,
            HashMap<Integer, List<Integer>> grap, boolean[] hasCircle) {
        
        if(hasCircle[0])    // 跳出条件
            return;
        else if(prevRoots.contains(start)) {
            hasCircle[0] = true;
            return;
        }
        
        prevRoots.add(start);
        List<Integer> match = grap.get(start);
        if(match != null) {
            for(Integer newStart: match)
                DFS(prevRoots, newStart, grap, hasCircle);
        }
        prevRoots.remove(start);
    }

 

posted @ 2018-10-24 19:53  skillking2  阅读(165)  评论(0编辑  收藏  举报