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.
Note:

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

所有需要学习的课程和其前置课程可以合成一张图;然后可以用经典BFS和DFS来完成题目。

BFS的主要思想是:每有一个可以学习的课程(前置课程为0或者前置课程已经学习完),学习它(已学习课程数加1),然后将所有以它为前置课程的课程所需前置课程数减1。依次,当所有可以学习的课程学习完后,查看是否满足总课程数。代码如下:

public boolean canFinish(int numCourses, int[][] prerequisites) {
        boolean[][] matrix = new boolean[numCourses][numCourses];//matrix[i][j]=true表示学习课程j需要先学习课程i
        int[] value = new int[numCourses];//value[i]表示学习课程i还需要的前置课程数量
        for(int i = 0; i < prerequisites.length; ++i) {
            int ready = prerequisites[i][0];//要学习的课程
            int pre = prerequisites[i][1];//所需的前置课程
            if(!matrix[pre][ready]) {
                value[ready]++;
            }
            matrix[pre][ready] = true;
        }
        Queue<Integer> queue = new ArrayDeque<>();//已经可以学习的课程队列
        for(int i = 0; i < numCourses; ++i) {//将所需前置课程数为0(即可以学习的课程)加入队列
            if(value[i] == 0) {
                queue.add(i);
            }
        }
        int count = 0;//表示已经学习的课程数
        while(!queue.isEmpty()) {//每次出队列的课程表示已经学习,将以该课程为前置课程的value减1
            int course = queue.poll();
            count++;
            for(int i = 0; i < numCourses; ++i) {
                if(matrix[course][i]) {//课程i需要前置课程course
                    if(--value[i] == 0) {//前置课程course已经学习,课程i所需前置课程减1;若课程i所需前置课程为0,则表示可以学习,加入队列
                        queue.add(i);
                    }
                }
            }
        }
        return count == numCourses;
    }

DFS的主要思想是:将所有课程构成一个有向图;边的起点表示前置课程,边的终点表示要学习的课程。对该有向图,要学习某一个课程,以该节点为起点进行深度优先搜索,若回到该节点(即构成一个环),则该课程无法完成学习,题目返回false。代码如下:

public boolean canFinish(int numCourses, int[][] prerequisites) {
        List<List<Integer>> graph = new ArrayList<>(numCourses);
        for(int i = 0; i < numCourses; ++i) {
            graph.add(new ArrayList<>());
        }
        for(int i = 0; i < prerequisites.length; ++i) {//将所有课程构成一个有向图;边的起点表示前置课程,边的终点表示要学习的课程
            graph.get(prerequisites[i][1]).add(prerequisites[i][0]);
        }
        boolean[] visited = new boolean[numCourses];//记录已经经过的节点
        for(int i = 0; i < numCourses; ++i) {//依次以每个课程节点为起点开始深度优先搜索,如果重复访问,则表示存在环,则不满足题意
            if(!dfs(graph, visited, i)) {
                return false;
            }
        }
        return true;
    }

    private boolean dfs(List<List<Integer>> graph, boolean[] visited, int i) {
        if(visited[i]) {
            return false;
        } else {
            visited[i] = true;
        }
        for(int j = 0; j < graph.get(i).size(); ++j) {
            if(!dfs(graph, visited, graph.get(i).get(j))) {
                return false;
            }
        }
        visited[i] = false;
        return true;
    }

上面为DFS方法,下面为BFS方法。明显看到DFS方法耗时多很多;这是因为DFS搜索的次数比BFS搜索的次数要多好多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值