当前位置: 首页 > news >正文

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

今天主要介绍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]=1for v in edges[current]:if state[v] ==1:has_circle=Truereturnelif state[v] ==0:dfs(v)if has_circle:returnelse: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 collectionsedges = 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_circlestate[u]=1for v in edges[u]:# print(v, state)if state[v]==0:dfs(v)if has_circle:return elif state[v] ==1:has_circle=Truereturnelse:continuestate[u]=2# res_stack.append()for i in range(numCourses):if not has_circle and  not state[i]:dfs(i)if has_circle:return Falsereturn True

相关文章:

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

今天主要介绍DAG (Directed acyclic graph),有向无环图。 无向图的问题相对有向图比较简单,比如岛屿问题,迷宫问题等。 在有向图中,我们通常只关注环是否存在,因为有向图中环的存在会让我们的…...

计算机视觉:图片数据的预处理

本文重点 图片数据是计算机视觉处理的核心,一般的图片数据并不能直接放到神经网络中,而是应该使用一些数据与处理的方式来解决,这个操作我们称为图片数据的预处理。 图像缩放 图像缩放是指将图像的尺寸调整为所需的大小。在AI中,图像缩放通常用于将图像调整为模型所需的…...

探秘C++中的神奇组合:std--pair的魅力之旅

探秘C中的神奇组合:std::pair的魅力之旅 引言std::pair简介及基本概念(An Overview and Basic Concepts of std::pair)std::pair的结构及构造方法(Structure and Construction Methods of std::pair)std::pair的常用成…...

Win10搭建我的世界Minecraft服务器「内网穿透远程联机」

文章目录 1. Java环境搭建2.安装我的世界Minecraft服务3. 启动我的世界服务4.局域网测试连接我的世界服务器5. 安装cpolar内网穿透6. 创建隧道映射内网端口7. 测试公网远程联机8. 配置固定TCP端口地址8.1 保留一个固定tcp地址8.2 配置固定tcp地址 9. 使用固定公网地址远程联机 …...

基于springboot和ajax的简单项目 02 代码部分实现,xml文件sql语句优化 (中)

上次说到了log/log_list.html的doGetObjects(),其中有doFindPageObjects()方法。 找到全部的日志对象,并且输出到div上。这里是后台的代码。 01.pojo对象,这里需要序列化保存。序列化的作用是保存对象到内存缓存中&am…...

LNMP架构部署

L:Linux A:Apache M:Mysql P:PHP 各组件的主要作用如下: (平台)Linux:作为LAMP架构的基础,提供用于支撑Web站点的操作系统,能够与其他三个组件提供更好的稳定性,兼容性(AMP组件也支持Windows、UNIX等平…...

SpringBoot 防护XSS攻击

目录 一、前言 1.1、XSS攻击流程 1.2、XSS攻击分类 1.3、攻击方式 二、解决方案 2.1、SPRINGBOOT XSS过滤插件(MICA-XSS) 2.2、MICA-XSS 配置 三、项目实战 3.1、项目环境 3.2、测试 3.2.1、测试GET请求 3.2.2、测试POST请求 3.2.3、测试POS…...

iOS 吸顶效果

项目中,在列表向上滚动时,有时需要将某个控件置顶,这就是我们常见的吸顶效果。 1. UITableView 吸顶效果 UITableView是自带吸顶效果,我们把需要置顶的控件设置为SectionHeaderView,这样在滚动时,该控件会…...

文本翻译免费软件-word免费翻译软件

好用的翻译文件软件应该具备以下几个方面的特点:支持多种文件格式,翻译结果准确可靠,界面操作简便易用,价格实惠,用户体验舒适。以下是几个好用的翻译文件软件: 1.147cgpt翻译软件 翻译软件特点&#xff1…...

redis 主从模式、哨兵模式、cluster模式的区别

参考: ​https://blog.csdn.net/qq_41071876/category_11284995.html https://blog.csdn.net/weixin_45821811/article/details/119421774 https://blog.csdn.net/weixin_43001336/article/details/122816402 Redis有三种模式,分别是:主…...

SDL(2)-加载图片

加载BMP 1.使用SDL_init初始化SDL库 2.使用SDL_CreateWindow创建一个窗口 3.使用SDL_GetWindowSurface获取创建窗口的surface 4.使用SDL_LoadBMP加载一张BMP图片 5.使用SDL_BlitSurface将加载的bmp surface拷贝到窗口的surface 6.使用SDL_UpdateWindowSurface更新到窗口 …...

指针数组和数组指针

指针和数组都是C语言中非常重要的概念。它们各自有其用途和应用场景。本文将介绍指针数组和数组指针,两者的区别和用法。 指针数组 指针数组是指一个数组,其中的每个元素都是一个指针类型。例如,下面这个定义了3个字符型指针的数组&#xf…...

程序员最常见的谎言

小伙伴们大家好,我是阿秀。 上周看到知乎上有位网友总结了自己的10年程序员生涯中最常说的一些谎言,一共有15条,看完我直呼内行!! 全中!每一枪都中了!每一条我都说过。 我基本都说过他说过的那些…...

hypothesis testing假设检验

假设检验是什么 比如一家巧克力工厂生产的巧克力每个1g,一个工人说,机器在维修之后生产的巧克力不是1g,为了验证工人说的是否正确,需进行假设检验。 随机挑选50个巧克力,计算平均重量。 H0:每个巧克力1g H…...

ChatGPT扩展系列之解决ChatGPT 被大面积封号的终极方案

ChatGPT扩展系列之解决ChatGPT 被大面积封号的终极方案 本节介绍了一个解决ChatGPT在中国大陆无法使用和担心被封号的问题的方法。近期有很多亚洲用户被封号,原因是有人滥用API接口或者批量注册账号,不符合官方规定。对于这个问题,提出了一个解决方法,可以在中国大陆无需翻…...

如何在DevOps中进行API生命周期管理?

引言 随着DevOps理念在中国企业当中的普及和发展,中国企业DevOps落地成熟度不断提升,根据中国信通院的数据已有近6成企业向全生命周期管理迈进。而在研发全生命周期管理之中,API管理的地位愈发显得重要。随着API数量的大幅增长,也…...

嵌套列表,与摩尔投票进阶

title: “Python fishC 22” author: “hou wei” date: “2023-04-16” output: html_document knitr::opts_chunk$set(echo TRUE)问答题 0.请问 运算符和 is 运算符有什么区别呢? 在Python中运算符用于比较两个变量的值是否相等,而is运算符用于判断…...

ChatGPT原理解释

写了一本介绍ChatGPT原理的课程 结构如下 01、介绍ChatGPT及其原理 1.1 ChatGPT的概述 1.2 什么是自然语言处理(NLP) 1.3 深度学习与NLP的关系 1.4 GPT模型的介绍 02、GPT原理探讨 2.1 GPT模型的输入与输出 2.2 GPT模型的结构 2.3 GPT模型的预训练方法…...

【配电网故障重构SOP】基于二阶锥松弛的加光伏风机储能进行的配电网故障处理和重构【考虑最优潮流】(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

ajax 的入门案例

一、ajax ajax,Asynchronous JavaScript And XML,异步的JavaScript和XML 同步:伴随着页面的刷新或跳转,即全局刷新;同步请求会阻塞代码的执行,即同步请求会一个一个的执行 异步:在不刷新页面…...

龙虎榜——20250610

上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

golang循环变量捕获问题​​

在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下: 问题背景 看这个代码片段: fo…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率&#xff0c…...

USB Over IP专用硬件的5个特点

USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...

2025季度云服务器排行榜

在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...

MFC 抛体运动模拟:常见问题解决与界面美化

在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...