java leetcode之[数据结构 中等]207. 课程表

题目的链接在这里:https://leetcode-cn.com/problems/course-schedule/


题目大意

你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。

在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程 bi 。

例如,先修课程对 [0, 1] 表示:想要学习课程 0 ,你需要先完成课程 1 。
请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false 。


一、示意图

在这里插入图片描述

二、解题思路

深度遍历和广度遍历

深度遍历

代码如下:

class Solution {
   List<List<Integer>> edges;
    //然后是判断是否有效
    boolean valid;
    //好像都不需要存数组
/*    //一个用来存数据的数组
    int[]res;
    //一个记录数组位置的
    int index;*/
    //一个判断对应的点有没有访问过 0表示没有访问过 1表示在访问中 2表示已经访问过了
    int visited[];
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        //这里就变成了 判断可不可以了  其实就是最后判断那个序列的长度等不等于 numCourses
        //先用用看DFS
        //首先就是需要构造这个有向图
        //开始初始化
        edges=new ArrayList<List<Integer>>();
        valid=true;
    /*    res=new int[numCourses];
        index=numCourses-1;*/
        visited=new int[numCourses];
        for(int i=0;i<numCourses;i++){
            edges.add(new ArrayList<Integer>());
        }
        //然后开始构造图
        for(int []infor:prerequisites){
            //数组是 a b的话 表示就是 从b指向a 这样子就构成边了
            edges.get(infor[1]).add(infor[0]);
        }
        //然后就是遍历 找到第一个没有被访问过的 然后就开始访问
        for(int i=0;i<numCourses&&valid;i++){
            //找到第一个没有被访问过的
            if(visited[i]==0){
                //那就进行递归
                dfs(i);
            }
        }
        //最后这里进行判断
        return valid;
    }

    private void dfs(int i) {
        //就开始深度遍历 首先进行改变
        //变成正在访问中
        visited[i]=1;
        //然后找从这个点出去的节点
        for(int v:edges.get(i)){
            //这里可能就会有好几个
            //如果没有访问过就进行访问  如果表示在访问中 那就说明有环 直接返回
            if(visited[v]==0){
                dfs(v);
            }
            else if(visited[v]==1){
                valid=false;
                return;
            }
        }
        //然后把这个点改成 已经完成了
        visited[i]=2;
    }
}

在这里插入图片描述

广度遍历

代码如下:

class Solution {
   List<List<Integer>> lists;
    //存储数组的计数
    int count;
    //然后记录每个点的入度
    int inDu[];
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        //然后是BFS 这个的话 要么就是通过这个这个最后的计数好了
        //开始初始化
        count=0;
        inDu=new int[numCourses];
        lists=new ArrayList<List<Integer>>();
        for(int i=0;i<numCourses;i++){
            lists.add(new ArrayList<Integer>());
        }
        //然后开始初始化 并且记录对应的入度
        for(int[] infor:prerequisites){
            //对应这个数组来说 他是 infor[1]->infor[0]
            inDu[infor[0]]++;
            //然后是边进行放入
            lists.get(infor[1]).add(infor[0]);
        }
        //然后创建一个队列 并将入度为0的全都放到队列中 并进行记录
        Queue<Integer> queue=new LinkedList<Integer>();
        for(int i=0;i<numCourses;i++){
            if(inDu[i]==0){
                //说明入度是0
                queue.add(i);
                count++;
            }
        }
        //然后开始一个个判断
        while (!queue.isEmpty()){
            int node=queue.poll();
            //然后更新node这个点出去的点 消除对应的入度
            for(int v:lists.get(node)){
                //他们对应的入度减一
                inDu[v]--;
                if(inDu[v]==0){
                    //那就进栈 并且进行更新
                    count++;
                    queue.add(v);
                }
            }
        }
        //最后就是判断count和numCourses的大小
        return count==numCourses;

    }
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值