代码随想录训练营 Day56打卡 图论part06 108. 冗余连接 109. 冗余连接II

news2024/11/26 5:41:05

代码随想录训练营 Day56打卡 图论part06

一、卡码108. 冗余连接

题目描述
有一个图,它是一棵树,他是拥有 n 个节点(节点编号1到n)和 n - 1 条边的连通无环无向图(其实就是一个线形图),如图:

现在在这棵树上的基础上,添加一条边(依然是n个节点,但有n条边),使这个图变成了有环图,如图:

先请你找出冗余边,删除后,使该图可以重新变成一棵树。
输入描述
第一行包含一个整数 N,表示图的节点个数和边的个数。
后续 N 行,每行包含两个整数 s 和 t,表示图中 s 和 t 之间有一条边。
输出描述
输出一条可以删除的边。如果有多个答案,请删除标准输入中最后出现的那条边。
输入示例
3
1 2
2 3
1 3
输出示例
1 3
提示信息

图中的 1 2,2 3,1 3 等三条边在删除后都能使原图变为一棵合法的树。但是 1 3 由于是标准输出里最后出现的那条边,所以输出结果为 1 3

  1. 树的性质:一棵树有 n 个节点和 n-1 条边,是一个连通且无环的图。如果给一棵树多加一条边,那么它就会形成一个环。
  2. 寻找冗余边:使用并查集来判断每次加边时,是否会形成环。如果发现某一条边连接的两个节点已经属于同一个连通分量(即它们已经连通),说明这条边是冗余的,即它会导致环的出现。
  3. 返回结果:根据题目要求,返回输入中最后出现的那条冗余边。

代码实现

class Solution:
    def findRedundantConnection(self, edges: list[list[int]]) -> list[int]:
        n = len(edges)  # 由于题目给定 n 条边,所以有 n 个节点
        parent = list(range(n + 1))  # 初始化并查集,每个节点的父节点初始化为它自己

        # 并查集的 find 函数,使用路径压缩优化
        def find(index: int) -> int:
            if parent[index] != index:  # 如果当前节点的父节点不是自己
                parent[index] = find(parent[index])  # 递归找到根节点,并将路径上的所有节点直接指向根节点
            return parent[index]  # 返回根节点
        
        # 并查集的 union 函数,合并两个节点所在的集合
        def union(index1: int, index2: int):
            parent[find(index1)] = find(index2)  # 将 index1 的根节点连接到 index2 的根节点
        
        # 遍历所有边,执行并查集的合并操作
        for node1, node2 in edges:
            if find(node1) != find(node2):  # 如果 node1 和 node2 不在同一个集合中
                union(node1, node2)  # 合并它们的集合
            else:
                return [node1, node2]  # 如果 node1 和 node2 已经在同一个集合中,说明这条边是冗余边
        
        return []  # 题目保证输入合法,所以不会执行到这里

卡码题目链接
题目文章讲解

二、卡码109. 冗余连接II

题目描述
有一种有向树,该树只有一个根节点,所有其他节点都是该根节点的后继。该树除了根节点之外的每一个节点都有且只有一个父节点,而根节点没有父节点。有向树拥有 n 个节点和 n - 1 条边。如图:

现在有一个有向图,有向图是在有向树中的两个没有直接链接的节点中间添加一条有向边。如图:

输入一个有向图,该图由一个有着 n 个节点(节点编号 从 1 到 n),n 条边,请返回一条可以删除的边,使得删除该条边之后该有向图可以被当作一颗有向树。
输入描述
第一行输入一个整数 N,表示有向图中节点和边的个数。
后续 N 行,每行输入两个整数 s 和 t,代表这是 s 节点连接并指向 t 节点的单向边
输出描述
输出一条可以删除的边,若有多条边可以删除,请输出标准输入中最后出现的一条边。
输入示例
3
1 2
1 3
2 3
输出示例
2 3
提示信息

在删除 2 3 后有向图可以变为一棵合法的有向树,所以输出 2 3

这道题的目的是在有向图中找到一条冗余边,该冗余边可以是多余的边或导致图中形成环路的边。具体解决思路是通过并查集和父节点数组相结合,来处理节点的父节点冲突以及环路检测问题。

题解思路

  1. 分析图的性质:
    树的性质:一棵树有 n 个节点和 n-1 条边,是一个无环的连通图。
    有向图的情况:给定的图有 n 个节点和 n 条边,多了一条附加的边,因此图可能会出现两种情况:
        · 有一个节点有两个父节点,即一个节点被指向两次。
        · 有环路,即一个节点可以通过有向边回到自己。
  2. 解决方法:
    记录每个节点的父节点:使用数组 parent 来记录每个节点的父节点。如果发现某个节点有两个父节点,说明存在冲突(conflict)。
    使用并查集检测环路:通过并查集(Union-Find)来检测是否有环路(cycle)。如果在合并时发现两个节点已经属于同一集合,说明这条边会导致环路。
    根据冲突和环路的情况返回结果
    如果有冲突但没有环路,那么冲突的边就是冗余边。
    如果同时有冲突和环路,优先返回与环路相关的边。
    如果没有冲突但有环路,返回环路中的最后一条边。

举个栗子

为什么优先删除与环路相关的边?
如果有冲突但没有环路,那么说明其中一条边只是使某个节点有两个父节点,此时直接删除指向该节点的后出现的那条边即可。

但如果同时存在父节点冲突和环路,此时导致问题的根源是环路,因为冗余边不仅让一个节点有两个父节点,还让整个图形成了一个环。优先删除与环路相关的边可以确保解决问题。

假设输入的图如下:

edges = [[1, 2], [2, 3], [3, 4], [4, 2], [1, 5]]

图的结构:

   1
  / \
 2 - 5
  |
  3
  |
  4
  |
  2  <-- 环路
  • 父节点冲突:边 [4, 2] 让节点 2 有两个父节点(分别是 1 和 4)。
  • 环路:2 → 3 → 4 → 2 形成一个环。

此时,我们要优先删除形成环的那条边,即 [4, 2],这样可以确保我们既消除了环路,又让图成为一棵树。

因此,在有冲突和环路的情况下,删除环路中的冗余边更能有效解决问题,避免冗余的边继续影响树的结构。

冲突是因为一个节点有多个父节点。
环路是因为多余的边使得整个图不再是树。

代码实现

class UnionFind:
    def __init__(self, n):
        # 初始化并查集,每个节点的祖先初始化为自己
        self.ancestor = list(range(n))
    
    # 合并两个节点所在的集合
    def union(self, index1: int, index2: int):
        # 找到两个节点的根,并将其中一个根指向另一个根
        self.ancestor[self.find(index1)] = self.find(index2)
    
    # 查找节点的根,同时进行路径压缩
    def find(self, index: int) -> int:
        if self.ancestor[index] != index:
            # 路径压缩,将当前节点的父节点直接指向根
            self.ancestor[index] = self.find(self.ancestor[index])
        return self.ancestor[index]

class Solution:
    def findRedundantDirectedConnection(self, edges: list[list[int]]) -> list[int]:
        n = len(edges)  # 图的节点数
        uf = UnionFind(n + 1)  # 初始化并查集
        parent = list(range(n + 1))  # 每个节点的父节点初始化为自己
        conflict = -1  # 记录冲突边的索引
        cycle = -1  # 记录环路边的索引
        
        # 遍历所有边
        for i, (node1, node2) in enumerate(edges):
            if parent[node2] != node2:
                # 如果 node2 已经有父节点,说明冲突发生,记录这条边
                conflict = i
            else:
                # 否则,更新 node2 的父节点为 node1
                parent[node2] = node1
                # 判断是否形成环路
                if uf.find(node1) == uf.find(node2):
                    # 如果 node1 和 node2 已经属于同一个集合,说明形成了环路
                    cycle = i
                else:
                    # 如果没有形成环路,将 node1 和 node2 合并到同一个集合
                    uf.union(node1, node2)
        
        # 如果没有冲突边,返回导致环路的那条边
        if conflict < 0:
            return [edges[cycle][0], edges[cycle][1]]
        else:
            # 处理冲突边
            conflictEdge = edges[conflict]
            if cycle >= 0:
                # 如果有环路,返回与环路相关的边
                return [parent[conflictEdge[1]], conflictEdge[1]]
            else:
                # 如果没有环路,直接返回冲突边
                return [conflictEdge[0], conflictEdge[1]]

时间复杂度

  • 查找和合并的均摊时间复杂度为 O(α(n)),其中 α(n) 是反阿克曼函数,近似为常数。
  • 遍历所有边的时间复杂度为 O(n)。
  • 总体复杂度接近 O(n)。

卡码题目链接
题目文章讲解

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

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

相关文章

Java面试篇基础部分-Java的类加载机制

JVM的类加载 JVM在运行Java文件的时候,类加载分为5个阶段:加载、验证、准备、解析、初始化。在类初始化加载完成之后,就可以使用这个类的信息了。当这个类不需要使用的时候,就可以从JVM进行卸载。 加载 加载是指JVM读取Class文件的操作,并且根据Class的文件描述创建对应的…

工厂安灯系统在优化生产流程上的优势丨深圳讯鹏科技

工厂安灯系统通过可视化的方式&#xff0c;帮助工厂管理者和操作工人及时了解生产状态&#xff0c;快速响应问题&#xff0c;从而优化生产流程。 一、安灯系统实时监控与反馈 安灯系统的核心功能是实时监控生产线的状态。通过在生产现场设置灯光、显示屏等设备&#xff0c;工人…

单片机拍照_将采集的RGB图像封装为BMP格式保存到SD卡

文章目录 一、前言二、BMP文件结构2.1 BMP图片的格式说明 2.2 RGB888与RGB565格式是什么&#xff1f;&#xff08;1&#xff09;RGB565&#xff08;2&#xff09;RGB888&#xff08;3&#xff09;区别&#xff08;4&#xff09;如何构成&#xff08;5&#xff09;示例 三、实现…

yolo训练出现Could not load library libcudnn_cnn_train.so.8问题及解决方法

问题场景&#xff1a; 训练yolov5或者yolov8时候会报错&#xff1a; Could not load library libcudnn_cnn_train.so.8. Error: /usr/local/cuda-12.1/lib64/libcudnn_cnn_train.so.8: uined symbol: _ZN5cudnn3cnn34layerNormFwd_execute_internal_implERKNS_7backend11Vari…

【EasyExcel】@ColumnWidth(value = 20) EasyExcel设置列宽不生效

经过测试发现&#xff0c;只有XLS&#xff0c;ColumnWidth注解才会生效&#xff0c;选择CSV和XLSX都不会生效 //对应的导出实体类 EasyExcel.write(outputStream, Result.class)//excel文件类型&#xff0c;包括CSV、XLS、XLSX.excelType(ExcelTypeEnum.XLS)

当你学会了Python,随手爬取电影榜单!

一、爬电影TOP250 python爬取电影TOP250数据&#xff01; 首先&#xff0c;打开电影TOP250的页面&#xff1a; https://movie.douban.com/top250 开发好python代码后&#xff0c;成功后的csv数据&#xff0c;如下&#xff1a; 代码是怎样实现的爬取呢&#xff1f;下面逐一讲…

计算机网络相关概念

名词解释&#xff1a; 1.ARPANET ARPANET&#xff08;Advanced Research Projects Agency Network&#xff09;是由美国国防部高级研究计划局&#xff08;ARPA&#xff09;在1969年启动的一个实验性计算机网络项目。它是世界上第一个分组交换网络&#xff0c;也是互联网的前身…

springboot《计算机网络》在线考试系统-计算机毕业设计源码22248

摘要 计算机网络课程是计算机科学与技术、信息技术及相关专业的一门重要课程。然而&#xff0c;在传统的教育模式下&#xff0c;计算机网络课程的考核方式多以纸质试卷为主&#xff0c;这种方式存在诸多弊端。一方面&#xff0c;试卷的编制、印刷、分发、收缴等环节耗时耗力&am…

遗传算法求解VRP路径规划问题

文章目录 题目&#xff1a;快递公司送货策略VRP问题简介遗传算法项目地址代码说明代码结构求解流程举例求解目标求解步骤 总结 打数模国赛前拿来练手的题&#xff0c;现在题目求解思路分享给大家&#xff0c;包括 所有源代码 和 高清pdf论文&#xff0c;希望能对大家有所帮助…

多线程篇(其它容器- CopyOnWriteArrayList)(持续更新迭代)

一、CopyOnWriteArrayList&#xff08;一&#xff09; 1. 简介 并发包中的并发List只有CopyOnWriteArrayList。 CopyOnWriteArrayList是一个线程安全的ArrayList&#xff0c;对其进行的修改操作都是在底层的一个复制的数 组&#xff08;快照&#xff09;上进行的&#xff0…

解决 git 不是内部或外部命令,也不是可运行的程序

目录 报错提示&#xff1a; 一、解决办法 1、从git官网下载windows版本的git 2、安装 3、注意事项 二、报错 1、解决 fatal: Not a git repository (or any of the parent directories): .git 问题 报错提示&#xff1a; 一、解决办法 Windows下配置Git&#xff1a; 1…

sap公司间交易(采购单转储)-公司间交易价格的配置

sap 公司间交易(采购单转储)-公司间交易价格的配置 对于通过采购单转储方式实现公司间交易,公司间交易价系统标准设计是,购货方采用采购单上的单价做为发票校验的价格,而销售方由于没有销售单,则采用的是在 vk11 里维护的公司间售价,这种做法的坏处是经常要同步这两个价格…

error C2275: 将此类型用作表达式非法-解决方案

最近在进行将C移植C的项目&#xff0c;代码改完&#xff0c;生成解决方案时&#xff0c;出现如下错误&#xff1a; 在移植c代码到c的时候&#xff0c;经常会出现一个奇怪的错误&#xff1a;“error C2275: “xxxxx”: 将此类型用作表达式非法” 两个错误属于同一类型&#xff…

投资一家无人机培训机构技术详解

无人机培训机构是随着无人机技术的快速发展和普及而兴起的一种专业培训机构。这类机构专注于为学员提供无人机相关的理论知识、操控技能以及应用技术培训&#xff0c;以满足不同领域对无人机人才的需求。 1. 市场调研与定位 市场调研 在投资无人机培训机构之前&#xff0c;深…

OpenWRT有三个地方设置DNS,究竟设置哪个地方会更好?

前言 刚上手OpenWRT软路由系统的小伙伴或许都会有这样的疑问&#xff1a;OpenWRT这个系统有三个地方是设置DNS的&#xff0c;究竟设置哪一个才是正确的&#xff1f; 这个还得从实际应用说起。 一般来说&#xff0c;咱们在使用路由器的时候&#xff0c;DNS都是默认运营商的DN…

YOLOV3实现越界检测——智能安防

目录 应用前景 1. 安全监控系统 2. 家庭安防系统 3. 无人机监控 4. 交通管理 5. 无人驾驶技术 6. 大型活动现场 代码说明 1. YOLO 模型加载 2. 摄像头视频流捕获 3. 安全区域绘制 4. YOLOv3 目标检测 5. 过滤和标记人类目标 6. 入侵检测 7. 结果显示和退出 总结…

黑神话怎么录?游戏录屏必备,探索2024年7款游戏录屏软件排行榜

在游戏世界中&#xff0c;记录下每一个精彩瞬间已成为玩家们的共同需求。2024年&#xff0c;随着《黑悟空神话》等大作的问世&#xff0c;玩家们对于游戏录屏软件的需求愈发高涨。本文将为您推荐几款在2024年备受好评的游戏录屏软件&#xff0c;帮助您捕捉游戏中的每一个高光时…

NLP-文本分类文献阅读-前置基础-词汇解释-通俗易懂-9月份-学习总结

目录 迁移学习 特征选择 特征工程 朴素贝叶斯分类方法 支持向量机 K-最近邻&#xff08;K-Nearest Neighbors, KNN&#xff09; 特征向量稀疏 卷积神经网络 循环神经网络 图神经网络 TextCNN 动态 K 最大池化 One-hot BOW Word2vec 池化&#xff08;Pooling&#xff09; 全连接…

Python画笔案例-043 绘制“篱笆“

1、绘制 “篱笆” 通过 python 的turtle 库绘制 “篱笆”&#xff0c;如下图&#xff1a; 2、实现代码 绘制 “篱笆”&#xff0c;以下为实现代码&#xff1a; """篱笆.py """ import turtledef draw_triangle():"""画正三角形函…