LeetCode207.课程表

 

 看完题我就想,这不就是进程里面的死锁问题嘛,进程1等进程2释放锁,进程2等进程3释放锁,进程3等进程1释放锁,这就造成了死锁。或者是spring中的循环依赖问题,BeanA的初始化需要初始化一个BeanB,BeanB的初始化需要初始化BeanA就出现了循环依赖。

我记得的死锁的判断是用简化图的方式,先找出能最先完成的进程,然后把这个点消掉,再找在等待这个进程的进程里面最容易完成看看能不能消掉,消到最后不能消,如果有环就会死锁  

 而spring中解决循环依赖问题用的是三级缓存就与这道题无关了

如果用简化图就太麻烦了,我就想用hashmap,我把prerequisites数组里的数据以k-v的形式存在HashMap里面,然后用get方法去拿到请求链中的节点放到一个set里面,如果这个节点早就在set中那么就出现了循环,于是几分钟就写出了下面的代码:

class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
           int n = prerequisites.length;
           Map<Integer, Integer> map = new HashMap<>();
           for(int i=0;i<n;i++){
               map.put(prerequisites[i][0],prerequisites[i][1]);
           }
           for(int i =0;i<n;i++){
               Integer key = prerequisites[i][0];
               Set<Integer> set = new HashSet<>();
               set.add(key);
               while(map.containsKey(key)){
                   if(set.contains(map.get(key))){
                       return false;
                   }else{
                       key = map.get(key);
                       set.add(key);
                   }
               }
               
           }
        return true;
    }
}

然后出错了,

因为我忽略了一门课的选修课有多门,hashmap如果key相同后面的value会覆盖前面的value。然后自己想了很久写没想出来然后就看题解了。

class Solution {
    List<List<Integer>> edges;
    int visit[];
    boolean valid = true;
    public boolean canFinish(int numCourses, int[][] prerequisites) {
           edges = new ArrayList<List<Integer>>();
           for(int i=0;i<numCourses;i++){
               edges.add(new ArrayList<Integer>());
           }
           visit = new int[numCourses];
           for(int[] info : prerequisites){
               edges.get(info[0]).add(info[1]);
           }
           for(int i=0;i<numCourses && valid;i++){
               if(visit[i] == 0){
                   dfs(i);
               }
           }
        return valid;

    }

    public void dfs(int u){
        visit[u] = 1;
        for(int v : edges.get(u)){
            if(visit[v] == 0){
                dfs(v);
                if(valid == false){
                    return;
                }
            }else if(visit[v] == 1){
                valid = false;
                return;
            } 
        }
        visit[u] = 2;
    }
}

 题解用的是深度优先搜索。如果我们把课程作为他的先修课的先行节点,我们可以得到一个图

 比如这个图就是要学A就必须先学F,E,C,要学F必须先学E,G,而E和G不需要先学其他课程,所以可以先把E和G学了然后F也可以学了....

题解用的是深度优先遍历可以结合下面的图更方便理解

 

它用List<List<Integer>> edges的结构构成一个图,外层的List放的是从0到numCourse-1门课程,内层放的是这门课程的先修课程。然后用一个int [] visited数组表是节点的状态,visit[i]=0表示还没有搜索i节点(上图中没有颜色的节点),visit[i]=1表示正在搜索这个节点(上图中黄色的节点),已经搜索过的节点(上图中绿色的节点),然后boolean valid是最后返回的结果,初始化为true,它只能被改成false不能被改成true,所以当有节点出现了死循环就把valid改成false,最后返回的valid就是false不可能是true。

然后先看dfs()方法:

public void dfs(int u){
        visit[u] = 1;
        for(int v : edges.get(u)){
            if(visit[v] == 0){
                dfs(v);
                if(valid == false){
                    return;
                }
            }else if(visit[v] == 1){
                valid = false;
                return;
            } 
        }
        visit[u] = 2;
    }

 课程u进入dfs后先把visit[u]从0改成1,表示正在访问u节点,然后通过edges.get(u),拿到u课程的所有先修课程vv,然后对这些先修课程v进行判断,

如果先修课程v的visit[v]=0,表示还没有搜索这个课程,递归调用dfs对它进行搜索;

如果visit[v]=1说明这个课程节点在之前已经开始搜索了但是还没有完成搜索,而又重新回到了这个节点,说明出现了环,那么就把valid改成false直接返回;

所以在前面visit[v]=0的情况下,dfs完了,如果valid变成了false就可以直接返回。

所以当visit[v]=2的时候,表示可以搜索到,不用做任何操作,直接进入判断下一个先行课;

当u的所有先修课程都判断完了并且没有出现valid改成fasle返回的情况,那么表明u的所有先修课都可以搜索到,那么u也可以搜索到了,把visit[u]改成2。

然后再看主方法:

 public boolean canFinish(int numCourses, int[][] prerequisites) {
           edges = new ArrayList<List<Integer>>();
           for(int i=0;i<numCourses;i++){
               edges.add(new ArrayList<Integer>());
           }
           visit = new int[numCourses];
           for(int[] info : prerequisites){
               edges.get(info[0]).add(info[1]);
           }
           for(int i=0;i<numCourses && valid;i++){
               if(visit[i] == 0){
                   dfs(i);
               }
           }
        return valid;

    }

 先对edges创建一个外层的List,然后再用for循环在这个外层List的每个节点上创建一个Lsit,创建一个visit数组,这都是初始化操作。然后再看下面这个for,他是edges.get(info[0])拿到了外层节点,然后再add(info[1])把先修课挂在了这个节点上,

题解用的是edges.get(info[1]).add(info[0]),我改成了edges.get(info[0]).add(info[1]),因为我觉得这样更好理解,两种都可以跑通。题解是按照上面的图来的,以课程作为他的先修课的先行节点,题解它其实是一个反向图,我们的目的是要判断有没有循环依赖,也就是有没有环,而有没有环与方向的正反无关。

然后只要把所有课程都dfs一遍就可以,for循环里面可以加上&&valid条件,这样一旦fasle后面就不用判断了,效率可以提高一点。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/167287.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

释放固态继电器的力量:主要优势和应用

固态继电器&#xff08;SolidStateRelay&#xff0c;缩写SSR&#xff09;&#xff0c;是由微电子电路&#xff0c;分立电子器件&#xff0c;电力电子功率器件组成的无触点开关。用隔离器件实现了控制端与负载端的隔离。固态继电器的输入端用微小的控制信号&#xff0c;达到直接…

软件项目可行性研究报告

一、可行性研究报告 1.1编写目的 1.2项目背景 1.3定义 1.4参考资料 2&#xff0e;可行性研究的前提 2.1要求 2.2目标 2.3条件、假定和限制 2.4可行性研究方法 2.5决定可行性的主要因素 3&#xff0e;对现有系统的分析 3.1处理流程和数据流程 3.2工作负荷 3.3费用…

俄罗斯操作系统Aurora OS 5.0全新UI亮相

俄罗斯媒体 IXBT 报道称&#xff0c;该地本土企业 Открытая мобильная платформа 于 2023 年 11 月 9 日至 10 日在圣彼得堡举行的 Mobius 2023 年秋季移动开发者专业会议上&#xff0c;展示了 Aurora OS 5.0 的界面和其他细节。 据介绍&#xff0c;…

美团外卖9元每周星期一开工外卖红包优惠券怎么领取?

美团外卖9元周一开工红包活动时间是什么时候&#xff1f; 美团外卖9元周一开工红包优惠券是指每周星期一可以领取的美团外卖红包优惠券&#xff0c;在美团外卖周一开工红包领取活动时间内可领取到9元周一开工美团外卖红包优惠券&#xff1b;&#xff08;温馨提醒&#xff1a;如…

git 提交成了LFS格式,如何恢复

平常习惯使用sourceTree提交代码&#xff0c;某次打开时弹出了一个【是否要使用LFS提交】的确认弹窗&#xff0c;当时不知道LFS是什么就点了确认&#xff0c;后续提交时代码全变成了这个样子 因为是初始化的项目首次提交&#xff0c;将近四百个文件全被格式化成了这个样子&…

UASRT(2)

UASRT参数配置 数据发送过程 1.双缓冲 当要发送三个数据 且是连续发送 第一个数据写入TDR寄存器 然后到移位寄存器发送&#xff08;一个一个bit的发送&#xff09;在第一个数据在移位寄存器发送的时候第二个数据就已经被写入TDR寄存器了等到第一个数据发送完第二个数据就进入…

2023年中国位置服务(LBS)产业链及市场规模分析[图]

卫星导航系统的高技术、高成本、高效益属性使其成为国家经济实力与科技实力的标志之一。卫星导航系统由空间段、地面段和用户段三个部分组成&#xff0c;已广泛用于交通运输、农林牧渔、航空航海等领域&#xff0c;服务载体包括手机、汽车、无人机、导弹等&#xff0c;对人们生…

Docker基础知识总结

文章目录 1.Docker介绍2.Docker版本3.为什么要使用Docker4.Docker基础组件4.1 镜像&#xff08;Images&#xff09;4.2 容器&#xff08;Container&#xff09;和仓库&#xff08;Repository&#xff09; 5.Docker安装6.Docker run7.Dockerfile8.Docker commit9.镜像发布到镜像…

深度学习之基于CT影像图像分割检测系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 基于CT影像的图像分割检测系统可以被设计成能够自动地检测出CT图像中的病变部位或解剖结构&#xff0c;以协助医生进…

[一周AI简讯]OpenAI宫斗;微软Bing Chat更名Copilot;Youtube测试音乐AI

OpenAI宫斗&#xff0c;奥特曼被解雇&#xff0c;董事会内讧 Sam Altman被解雇&#xff0c;不再担任CEO&#xff0c;董事会的理由是奥特曼在与董事会的沟通中始终不坦诚&#xff0c;阻碍了董事会履行职责的能力。原首席技术官Mira Murati担任新CEO。OpenAI宫斗剧远未结束&…

Python的requests库:解决文档缺失问题的策略与实践

在Python的requests库中&#xff0c;有一个名为ALL_PROXY的参数&#xff0c;但是该参数的文档并未进行详细的描述。这使得用户在使用该参数时可能会遇到一些问题&#xff0c;例如不知道如何正确地配置和使用该参数。 解决方案 针对这个问题&#xff0c;我们可以采取以下几种解…

[Kettle] 生成记录

在数据统计中&#xff0c;往往要生成固定行数和列数的记录&#xff0c;用于存放统计总数 需求&#xff1a;为方便记录1~12月份商品的销售总额&#xff0c;需要通过生成记录&#xff0c;生成一个月销售总额的数据表&#xff0c;包括商品名称和销售总额两个字段&#xff0c;记录…

深度学习之基于YoloV5-Pose的人体姿态检测可视化系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 深度学习之基于 YOLOv5-Pose 的人体姿态检测可视化系统介绍YOLOv5-Pose 简介系统特点系统架构使用方法 二、功能三、系统四. 总结 一项目简介 深度学习之基…

金融市场数据至上:QuestDB 为您的数据提供最优解 | 开源日报 No.81

vlang/v Stars: 34.7k License: MIT V 是一个开源项目&#xff0c;它是一种简单、易于学习的编程语言。该项目具有以下核心优势和主要功能&#xff1a; 简洁性&#xff1a;可以在周末内掌握这门语言。快速编译&#xff1a;使用 Clang 后端约为 110k loc/s&#xff0c;本地和…

【grafana | clickhouse】实现展示多折线图

说明&#xff1a; 采用的是 Visualizations 的 Time series&#xff0c;使用的 clickhouse 数据源 在工作中遇到了一个需求&#xff0c;写好了代码&#xff0c;需要在grafana上展示在一个项目中所有人的&#xff0c;随时间的代码提交量变化图 目前遇到的问题&#xff1a;展示…

jetbrains ai 提示该地区不可用的百分百解决方案,亲测有效

问题 申请 jetbrains 的 ai assistant 白名单已经通过&#xff0c;但是在使用 ai assistant 的过程中提示 The usage of the service is not permitted in your location ,我所在的地区是中国&#xff0c;目前该插件是对中国大陆关闭的。 刚开始我怀疑是代理的问题&#xff…

2023年中国负极材料分类、产量及市场规模分析[图]

锂离子电池主要由正极、负极、隔膜、电解液、电池外壳组成。负极材料是锂离子电池的重要原材料之一&#xff0c;对于锂离子电池起关键作用。在充电过程负极材料中不断地与锂离子发生反应&#xff0c;将锂离子“擒获并存储”起来&#xff0c;亦将外部的功以能量的形式存储在电池…

1688API接口接入|阿里1688-B类电商基础链路专业化体验升级

新挑战&#xff0c;新契机&#xff01; 当下整个互联网的竞争环境的变化为我们带来新的机遇和挑战。1688作为连接中小生产商、贸易商和零售商的源头货源首选平台&#xff0c;持续不断地为B类买家提供更专业的服务和更优质的源头厂货供给&#xff0c;打造核心竞争力。 面对新的…

数据结构与算法编程题3

长度为n的顺序表&#xff0c;删除线性表所有值为x的元素&#xff0c;使得时间复杂度为O(n)&#xff0c;空间复杂度为O(1) #include <iostream> using namespace std;typedef int ElemType; #define Maxsize 100 #define OK 1 #define ERROR 0 typedef struct SqList {E…

回顾以前的java

System.out.println(card1);打印的是对象的话会自动调用我们重写的toString方法 这个方法通常在Object类中定义&#xff0c;所有的Java类都继承自Object类 实例方法有个this,谁调用这个方法谁就是this 1.练习重写实例方法,调用this 调用object的equals,实际是判断地址相不相等…