【LeetCode 图论 一】初探有向图Directed Graph

news2024/11/16 22:01:26

今天主要介绍DAG (Directed acyclic graph),有向无环图。

无向图的问题相对有向图比较简单,比如岛屿问题,迷宫问题等。

在有向图中,我们通常只关注环是否存在,因为有向图中环的存在会让我们的程序陷入死循环。

举个例子,有向图中的方向通常指代一些事情的执行顺序,比如说[a, b], [b, c]
我们假设a,b,c是三门课程,要学左边的课程之后才能学右边的课程,所以这里我们如果要学c,就要先学a,再学b,最后才能学c。
那如果有环,【a,b】,【b,a】,显然这是矛盾的。
同样。对于一些列复杂的课程
在这里插入图片描述
若我们想学5,则要先学3,要学3则要先学4,而要学4则要先学5…这无解
这会让我们DFS的搜索陷入循环。
所以一般我们进行搜索的时候,需要判断环是否存在。

另外我们还要提一下【拓扑排序
刚刚的课程选择问题中,是一种优先级限制下的调度问题,在有向图中它的定义是
在满足限制条件的情况下如何安排并完成所有任务。
我们可以画出一张有向图,顶点对应任务(通过数组索引来表示课程),有向边对应优先级顺序。
而有向图中的优先级限制下的调度问题,等价于【拓扑排序】,它的定义是:
给定一副有向图,将所有的顶点排序,使得所有的有向边均从排在前面的顶点指向排在后面的顶点。 如下图
在这里插入图片描述
同学可以按照上面排序之后的有向图修完所有课程。

我们利用DFS寻找环:

维护一个递归调用期间已访问的顶点的栈Stack,若(在递归调用期间,通过判断onStack标记数组)两次访问了某个顶点,则说明有环;若DFS递归调用完毕,说明无环。

上面说的还是比较抽象。但是已经大致有一个印象了,就是,有向无环图因为它的顺序限制原因,已经搜索完的点,是不可能再次回到它这里的。

具体的,我们参考上面拓扑排序的图,当搜索到某个点,它没有相邻节点,它就入栈。
所以最终结果是,我们将 最后的课程4放在了栈底,最初的课程8放在栈的最顶部。

由于搜索是从随机的点开始的,我们将没有相邻节点的点入栈之后,再回溯到初始节点,将它入栈,但是后面的搜索也可能会碰到它。所以要给已经搜索的节点打上标签。

另外要注意一点,有些情况下会提示图中无环,但是有些题目不会提示,所以我们考虑一下再搜索过程中判断是否有环,具体的,对于某些节点X,我们搜索过,但是因为我们还没找到那个没有相邻节点的点end,或者我们还没有从end回溯到X,那么此时X节点的状态就是【搜索中】,如果我们搜索的过程中,两次搜索到X,那说明到X节点的图不是单向的,而是存在一个环。

所以,我们将节点分类为【搜索中】【已搜索】【未搜索】
假设有一对相邻节点(u,v),方向是u到 v 。
我们从u开始搜索,此时需要判断v的状态
【v是未搜索】:那我们可以搜索v,搜索完成之后,回溯到u 。
【v是搜索中】:那表示有一个环经过了v节点,这种情况下不存在拓扑排序。
【v是已搜索】:那v已经入栈了,而u不在栈中,那么u入栈就和v没关系,只看u自己的其他相邻节点来决定它的入栈时间即可。

下面用题目演示更直白

LeetCode 210 课程表II

https://leetcode.cn/problems/course-schedule-ii/

现在你总共有 numCourses 门课需要选,记为 0 到 numCourses - 1。
给你一个数组 prerequisites ,其中 prerequisites[i] = [ai, bi] ,
表示在选修课程 ai 前 必须 先选修 bi 。

例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示:[0,1] 。
返回你为了学完所有课程所安排的学习顺序。可能会有多个正确的顺序,你只要返回 任意一种 就可以了。如果不可能完成所有课程,返回 一个空数组 。

实例1
输入:numCourses = 2, prerequisites = [[1,0]]
输出:[0,1]
解释:总共有 2 门课程。要学习课程 1,你需要先完成课程 0。因此,正确的课程顺序为 [0,1] 。

实例2
输入:numCourses = 4, prerequisites = [[1,0],[2,0],[3,1],[3,2]]
输出:[0,2,1,3]
解释:总共有 4 门课程。要学习课程 3,你应该先完成课程 1 和课程 2。并且课程 1 和课程 2 都应该排在课程 0 之后。
因此,一个正确的课程顺序是 [0,1,2,3] 。另一个正确的排序是 [0,2,1,3] 。

实例3
输入:numCourses = 1, prerequisites = []
输出:[0]
import collections
class Solution:
    def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:          
        edges = collections.defaultdict(list) # 有向图的表达方式
        for x in prerequisites:
            edges[x[1]].append(x[0]) # 每个点 和 它能到的相邻节点

        has_circle = False #是否包含环

        res = [] # 栈底是没有相邻节点的点,栈顶是源点,返回res[::-1]

        state = [0]*numCourses# 0 1 2 代表未搜索 搜索中,已搜索

        def dfs(current):
            nonlocal has_circle # nonlocal:函数之外定义,函数之内改变值
            state[current]=1
            for v in edges[current]:
                if state[v] ==1:
                    has_circle=True
                    return
                elif state[v] ==0:
                    dfs(v)
                    if has_circle:
                        return
                else:
                    continue 
            state[current]=2 # 每次的dfs会添加一个节点到栈底,这个节点没有指向任何节点
            res.append(current)
              
        for i in range(numCourses):
            if not has_circle and not state[i]:
                dfs(i)
            if has_circle:
                return []
        
        return res[::-1]

LeetCode 207 课程表

https://leetcode.cn/problems/course-schedule/

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

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

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


示例 1:

输入:numCourses = 2, prerequisites = [[1,0]]
输出:true
解释:总共有 2 门课程。学习课程 1 之前,你需要完成课程 0 。这是可能的。
示例 2:

输入:numCourses = 2, prerequisites = [[1,0],[0,1]]
输出:false
解释:总共有 2 门课程。学习课程 1 之前,你需要先完成​课程 0 ;并且学习课程 0 之前,你还应先完成课程 1 。这是不可能的。

解答方法就是判断这个有向图中有没有环。比上一题更简单。


class Solution:
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        # 不能完成的几个情况    
        # 图中有环,自相矛盾
        import collections
        edges = collections.defaultdict(list)
        for x in prerequisites:
            edges[x[1]].append(x[0])

        state = [0]*numCourses # 0 1 2 未搜索 搜索中 已搜索

        has_circle = False

        # res_stack = []

        def dfs(u):
            nonlocal has_circle
            state[u]=1
            for v in edges[u]:
                # print(v, state)
                if state[v]==0:
                    dfs(v)
                    if has_circle:
                        return 
                elif state[v] ==1:
                    has_circle=True
                    return
                else:
                    continue
            state[u]=2
            # res_stack.append()
        for i in range(numCourses):
            if not has_circle and  not state[i]:
                dfs(i)
            if has_circle:
                return False
        return True

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HBuilderX的快捷键 和 常见配置

快捷键说明ctrl /添加注释&#xff08;js&#xff1a;// 注释、css&#xff1a;/* 注释 */、vue/nvue模板&#xff1a; <!-- 注释 -->&#xff09;Ctrl C 拷贝当前行或者所选代码块到剪切板Ctrl X剪切当前行或所选代码块到剪切板Ctrl V粘贴剪切板上的内容Ctrl D 删除…

浏览器实时查看日志系统-log.io

标题 前言操作步骤1. Install server via npm安装Nodejs2. Launch server3. Install file input via npm4. Configure file input前言 log.io 是一个实时日志监控工具,采用 node.js + socket.io 开发,使用浏览器访问,每秒可以处理超过5000条日志变动消息。有一点要指出来的…

叔可忍婶不可忍!马斯克3月呼吁暂停人工智能,4月却创立TruthGPT

2018年马斯克退出了OpenAI团队。 2022年11月&#xff0c;ChatGPT在北美大陆问世。 2023年3月21日&#xff0c;马斯克在未来生命&#xff0c;签署并呼吁&#xff0c;暂停高级人工智能的研发。 2023年4月18日马斯克创立了TruthGPT。 同时&#xff0c;亚马逊&#xff0c;也创立了B…

提桶跑路转行到软件测试,鬼知道我经历了什么?很庆幸转行成功...

说来惭愧&#xff0c;我的大学不是985也不是211&#xff0c;不过地质学科群一直排名国内前几&#xff0c;2017年也藉由地质学学科评上了“双一流”。咱们土木工程跟着沾沾光&#xff0c;也能和别人吹吹牛逼&#xff0c;所以毕业后的工作基本上在省内是不愁的。 但是我还是低估了…

“全自主、全流程、全覆盖”2023实景三维新技术研讨会广州站圆满举行!

4月12日&#xff0c;由中国测绘学会、中国地理信息产业协会指导&#xff0c;广州省测绘学会主办&#xff0c;武汉大势智慧科技有限公司承办的全自主、全流程、全覆盖”2023实景三维新技术研讨会广州站在广州珠江宾馆隆重举行。 本次会议广东省测绘学会、地图院、测绘院、市城市…

ChatGPT促进中国大语言模型发展,底层标注数据质量成关键,景联文科技提供专业数据采集标注服务

自开年以来&#xff0c;ChatGPT的热浪带来了一场全民的科技狂欢&#xff0c;同时打开了业内对NLP发展的想象空间&#xff0c;拉开了大语言模型产业和生成式AI产业飞速发展的序幕。 海外市场中OpenAI、微软、谷歌、Meta等巨头都在积极争抢布局ChatGPT&#xff0c;中国市场中百度…

NIFI大数据进阶_NIFI的模板和组的使用-介绍和实际操作_创建组_嵌套组_模板创建下载_导入---大数据之Nifi工作笔记0022

然后我们来看一下如何操作模板 首先我们准备好了一个模板,叫做CsvToJSON这样一个模板文件了 然后我们再来看左下角有个上传模板 可以选择这个模板上传上来,然后,就可以在右侧找到,菜单,找到template,点击,来查看模板了 然后添加组,就是顶部的那个两个圆圈的组件拖过来以后用来…

android compiled_local_resources\debug\out‘ is not a readable directory.

需要删除android目录下的.gradle文件。如下文件即可&#xff1a;

PyTorch实战1:实现mnist手写数字识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f366; 参考文章&#xff1a;365天深度学习训练营-第P1周&#xff1a;实现mnist手写数字识别&#x1f356; 原作者&#xff1a;K同学啊|接辅导、项目定制 目录 一、 前期准备1. 设置GPU2. 导入数…

EPICS Archiver Appliance在Debian11 容器下安装文档

PC安装虚拟化平台趟坑记录 上面proxmox在pc上安装好之后&#xff0c;相关的后台开始搭建&#xff0c;首先是AA数据存档服务。 EPICS Archiver Appliance在Debian11下安装文档 上面文档是晓康整理的&#xff0c;还一直没空完整的按流程做一遍&#xff0c;正好就着proxmox平台在…

【MySQL | 进阶篇】08、InnoDB 引擎架构、事务原理及 MVCC 讲解

目录 一、逻辑存储结构 二、架构 2.1 概述 2.2 内存结构 2.2.1 Buffer Pool 2.2.2 Change Buffer 2.2.3 Adaptive Hash Index 2.2.4 Log Buffer 2.3 磁盘结构 2.3.1 System Tablespace 2.3.2 File-Per-Table Tablespaces 2.3.3 General Tablespaces 2.3.4 Undo T…

Hbase1.3:Hbase基础架构、Hbase基础架构角色:Master、Region Server、Zookeeper、HDFS

Hbase1.3&#xff1a;Hbase基础架构、Hbase基础架构角色&#xff1a;Master、Region Server、Zookeeper、HDFS Hbase基础架构Hbase基础架构角色1&#xff09;Master2&#xff09;Region Server3&#xff09;Zookeeper4&#xff09;HDFS Hbase基础架构 Hbase架构里面&#xff0…

ubuntu18.04手动安装网卡驱动,重启系统后,驱动消失的解决方案

ubuntu18.04手动安装网卡驱动&#xff0c;重启系统后&#xff0c;驱动消失的解决方案 文章目录 ubuntu18.04手动安装网卡驱动&#xff0c;重启系统后&#xff0c;驱动消失的解决方案 1.问题描述2.问题分析3.解决方案&#xff08;使用 Netplan 配置网络&#xff09; 参考&#x…

XXL-JOB介绍

一、介绍 1.1、什么是XXL-JOB XXL-JOB是一个分布式任务调度平台&#xff0c;用于解决分布式系统中定时任务执行问题 1.2、架构图 二、部署 2.1、源码部署 2.1.1、下载源码 gitee下载地址 github下载地址 2.1.2、初始化数据库 2.1.3、修改数据库配置 2.1.4、将xxl-job-admi…

Java泛型--Java中的E、T、?

&#x1f341; 先说结论&#xff1a; T、E、K、V、&#xff1f;本质都是通配符。用于定义泛型类、泛型方法、泛型接口…换成其他字母也行&#xff0c;只是这几个字母是一种编码约定。T&#xff0c;即type&#xff0c;表示一个具体的Java类型E&#xff0c;即element&#xff0c;…

2023测试人必备60个实用测试工具推荐,让你成为测试大咖

目录 引言 一、测试管理工具 二、接口测试工具 三、性能测试工具 四、C/S自动化工具 五、白盒测试工具 六、代码扫描工具 七、持续集成工具 八、网络测试工具 九、app自动化工具 十、web安全测试工具 绵薄之力 引言 无论你是一名资深测试人员还是刚入行的新手&…

大数据实战 --- 世界新冠疫情数据分析

目录 开发环境 数据描述 功能需求 数据准备 统计计算 Hbase Hive 分析数据 开发环境 HadoopHiveSparkHBase 启动Hadoop&#xff1a;start-all.sh 启动zookeeper&#xff1a;zkServer.sh start 启动Hive&#xff1a; nohup hiveserver2 1>/dev/null 2>&1 &…

基于多种流量检测引擎识别pcap数据包中的威胁

在很多的场景下&#xff0c;会需要根据数据包判断数据包中存在的威胁。针对已有的数据包&#xff0c;如何判断数据包是何种攻击呢&#xff1f; 方法一可以根据经验&#xff0c;对于常见的WEB类型的攻击&#xff0c;比如SQL注入&#xff0c;命令执行等攻击&#xff0c;是比较容…

Radzen Blazor Studio 2.84 Crack

Radzen Blazor Studio 是一种桌面工具&#xff0c;它使 开发人员 能够创建漂亮的商业 Blazor 应用程序。快速地。 开放技术栈 没有供应商锁定。生成的源代码是人类可读的&#xff0c;您可以使用免费工具构建它。 Radzen 由流行的开源技术——ASP.NET Core、Blazor、Bootstrap …

Handler消息机制

App中一般多会有多个线程&#xff0c;多线程之间难免需要进行通信。开发中线程通信用的最多的就是Handler&#xff0c;另外还有&#xff0c;例如子线程进行数据处理&#xff0c;在主线程中进行UI更新。 当然了除了Handler这种通信方式外&#xff0c;线程间的通信还有其他几种方…