算法-Redundant Connection-冗余连接

本文主要探讨了如何解决寻找无环图中一条删除后能保持无环的冗余边的问题。通过模拟树的构建过程,利用根节点判断新加入边是否会形成环。当新边两端节点的根节点相同时,即为冗余边。通过示例解释了判断逻辑,并提供了使用数组和查找函数实现的解决方案,最后分析了算法的空间复杂度和时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、题目介绍

在本问题中, 树指的是一个连通且无环的无向图。
输入一个图,该图由一个有着N个节点 (节点值不重复1, 2, ..., N) 的树及一条附加的边构成。附加的边的两个顶点包含在1到N中间,这条附加的边不属于树中已存在的边。
结果图是一个以边组成的二维数组。每一个边的元素是一对[u, v] ,满足 u < v,表示连接顶点u 和v的无向图的边。
返回一条可以删去的边,使得结果图是一个有着N个节点的树。如果有多个答案,则返回二维数组中最后出现的边。答案边 [u, v] 应满足相同的格式 u < v。

示例 1:
输入: [[1,2], [1,3], [2,3]]
输出: [2,3]
解释: 给定的无向图为:
  1
 / \
2 - 3
      
示例 2:
输入: [[1,2], [2,3], [3,4], [1,4], [1,5]]
输出: [1,4]
解释: 给定的无向图为:
5 - 1 - 2
    |   |
    4 - 3

2、题目分析

  • 有N的顶点的无环图/树,有N-1条边,现在的任务是找到一条冗余边,删掉之后有环的图变无环

  • 模拟一个树建立的过程,将边一条条的加入,在一条边加入之前,两端的节点除了这条边应该没有其他的路径相连接,需要判断新加入的两条边有没有连接的路径

  • 要判断已知的连接,需要使用一种形式来记录保存原来的点之间的关系,根据树的节点的关系可以知道,相连的节点有唯一的根节点

  • 根据以上的信息,可以知道新加入的边的两端节点,如果在加人之前的根节点相等,则加入之后会形成环

  • 例如实例1:

    [1,2]表示2的上一个节点是1,1和2不断向上找到根节点,如果二者的根节点相同则说明出现环

    1->2,2的根节点是2,1的根节点是1,判断两者不相等,将1->2加入记录,2的根节点更新为1

    1->3,3的根节点是3,1的根节点1, 判断两者不相等,将1->3加入记录,3的根节点更新为1

    2->3,2的根节点是1,3的根节点也是1,两者相等,返回这两个节点

  • 这里使用数组来保存两个节点之间的关系,使用一个查找函数来寻找根节点

3、代码实现

class Solution {
    public int[] findRedundantConnection(int[][] edges) {
        int[] parents = new int[edges.length + 1];//parents[i]=j表示i的上一个节点是j
        for(int[] edge : edges){
            int node1_root = findRoot(parents,edge[0]);
            int node2_root = findRoot(parents,edge[1]);
            if(node1_root == node2_root) return edge;//相等就返回
            else parents[node2_root] = node1_root;//不想等就加入记录
        }
        return null;
    }
    private int findRoot(int[] parents,int node){//查找函数
        if(parents[node] > 0) return findRoot(parents,parents[node]);//向上寻找根节点
        else return node;//上一个节点不存在时证明这个节点就是根节点
    }
}

4、复杂度分析

  • 空间复杂度:O(N)
  • 时间复杂度:O(N)
### 力扣上的并查集示例题目 #### 题目概述 在 LeetCode 上,并查集是一种非常常见的算法设计模式,用于解决涉及连通性和分组的问题。以下是几个经典的并查集相关题目及其描述。 --- #### 经典题目解析 1. **岛屿数量 (Number of Islands)** 这是一个经典问题,目标是在二维网格中计算由 '1' 表示的陆地组成的岛屿的数量[^2]。可以使用 DFS、BFS 或者并查集来实现。如果选择并查集方法,则可以通过 `union` 操作将相邻的陆地标记为同一集合,最终统计独立集合的数量得到答案。 2. **最长连续序列 (Longest Consecutive Sequence)** 输入一个未排序的整数数组,找到其中最长的连续子序列长度[^3]。此问题可以用哈希表或者并查集求解。通过构建节点之间的连接关系,利用并查集中的 `find` 和 `union` 方法动态维护最大连通区域大小。 3. **朋友圈 (Friend Circles)** 描述了一群学生之间是否存在友谊关系的情况,判断总共有多少个互不相交的朋友圈[^1]。这道题可以直接映射到标准的并查集模型上——每一对朋友视为一条边,执行相应的合并操作后查询总的连通分支数目即可得出结果。 4. **账户合并 (Accounts Merge)** 提供多个电子邮件地址列表以及它们所属用户的姓名信息,要求按照实际拥有这些邮箱的人重新整理输出形式[^4]。这里同样适用基于字符串键值建立图结构再借助并查集完成归类处理逻辑。 5. **冗余连接 II (Redundant Connection II)** 假设树形拓扑被破坏成含有环路的状态,请找出造成这种情况的一条多余边并移除恢复原状。运用带权版并查集技巧检测何时形成闭环从而定位错误链接位置。 --- ```python class UnionFind: def __init__(self, n): self.parent = list(range(n)) def find(self, p): while p != self.parent[p]: self.parent[p] = self.parent[self.parent[p]] # 路径压缩 p = self.parent[p] return p def union(self, p, q): rootP = self.find(p) rootQ = self.find(q) if rootP == rootQ: return False self.parent[rootP] = rootQ return True ``` 上述代码片段展示了如何定义一个基础版本的支持按秩合并与路径压缩优化后的并查集数据结构实例化过程。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值