每日一题算法:2020年8月4日 [课程表]canFinish

2020年8月4日 课程表 canFinish

在这里插入图片描述

class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
    }
}

解题思路:

首先要读懂题目,一开始我以为题目的介绍不够明确,有很多的疑问,然后去查阅资料,了解了什么是边缘列表表示的图形。

因为给我们的数组是一个边缘列表,所以,二维数组的大小是N*2,每一个子数组都只有两个数字,也就是要修第一门课必须先修第二门课,这是一个有方向的关系。

具体内容可以看下面这篇博客:

https://blog.csdn.net/weixin_44925547/article/details/106388839

我们可以选择使用该边缘列表做出这一个有向图,然后在有向图的基础上进行计算,或者直接在边缘列表上进行计算。

还有,经过我的测试,实际上题目的描述并不准确,会存在某一门课既不是其他课程的先修课,也不需要任何一门先修课的课程:

在这里插入图片描述

但是不会出现课程少于能选修的课的情况(没有预期结果说明没有该输入类型)

下图中1表示必须修够的课程为1门,此时有两门课,1需要先修0,0没有先修课,此时0应该是能够修的课,但是题目中却没有答案。
在这里插入图片描述

也就是说我们不需要考虑这种情况。图中出现的节点个数不会超过numCourse-1这个数字。但是图中有关联的节点数可以少于这个数字。

用图来表示的话就是这样:

在这里插入图片描述
在这里插入图片描述

这也就是代表我们只需要判断能否达到图中的所有节点就可以了,不需要考虑部分节点不能达到但是能够修完numCourse门课的可能。

代码实现:

我没有想到如何使用边缘列表来进行计算,所以

//用于记录每一门课程修完之后的后续课程
HashMap<Integer, HashSet<Integer>> map=new HashMap<>();
//记录每一个课程的先修课数
int[] courses;
public boolean canFinish(int numCourses, int[][] prerequisites) {

    int len=prerequisites.length;
    courses=new int[numCourses];
    //给每一门课程增加他们的先修课关系
    for (int i=0;i<len;i++){
        if (map.get(prerequisites[i][1])==null)
            map.put(prerequisites[i][1],new HashSet<>());
        map.get(prerequisites[i][1]).add(prerequisites[i][0]);
        courses[prerequisites[i][0]]++;
    }

    //检查他们的先修课关系
    for(int i=0;i<numCourses;i++){
        //如果课的先修课已经修完,将后续课程的先修度-1
        if (courses[i]==0){
            remove(courses[i]);
        }
    }
    for (int i=0;i<numCourses;i++)
    {
        if (courses[i]!=0)
            return false;
    }
    return true;
}
//通过输入
public void remove(int course1){

    if (map.get(course1)==null)
        return;
    for (Integer integer : map.get(course1)) {

        courses[integer]--;
        if (courses[integer]==0){
            remove(integer);
        }

    }
    map.put(course1,null );
}

有点bug,没来得及改。

©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页