题目描述
树可以看成是一个连通且 无环 的 无向 图。
给定往一棵 n
个节点 (节点值 1~n
) 的树中添加一条边后的图。添加的边的两个顶点包含在 1
到 n
中间,且这条附加的边不属于树中已存在的边。图的信息记录于长度为 n
的二维数组 edges
,edges[i] = [ai, bi]
表示图中在 ai
和 bi
之间存在一条边。
请找出一条可以删去的边,删除后可使得剩余部分是一个有着 n
个节点的树。如果有多个答案,则返回数组 edges
中最后出现的边。
示例 1:
输入: edges = [[1,2], [1,3], [2,3]]
输出: [2,3]
示例 2:
输入: edges = [[1,2], [2,3], [3,4], [1,4], [1,5]]
输出: [1,4]
提示:
n == edges.length
3 <= n <= 1000
edges[i].length == 2
1 <= ai < bi <= edges.length
ai != bi
edges
中无重复元素- 给定的图是连通的
解题思路
本题要找出冗余的连接,即当前某个连接不连接,依然可以保证所有节点已经连通。
所以可以遍历输入数组,将两个节点合并到一个集合,如果遍历到某条边,当前两节点已经处于同一集合,则说明该边是一条可以删除的边。\
代码实现
// 如果两个顶点是一个连通分量,闭环,附加边,返回附加边
// 如果两个顶点不是一个连通分量,不会闭环,也没有附加边,也没有附加边,合并两个顶点;
var findRedundantConnection = function(edges) {
let nodeCount = edges.length;
let uf = new UnionFind(nodeCount);
for(let i = 0; i < nodeCount; i++){
let edge = edges[i];
let node1 = edge[0],node2 = edge[1];
if(uf.findSet(node1) != uf.findSet(node2)){
uf.unite(node1,node2)
}else{
return edge;
}
}
return [0];
};
class UnionFind{
constructor(n){//初始化:并查集里面的所有节点的父节点都是自己
this.parent = new Array(n).fill(0).map((value,index)=>index);
this.size = new Array(n).fill(1); //初始化集合
this.setCount = n;//联通分量
}
findSet(index){
if(this.parent[index] != index){
this.parent[index] = this.findSet(this.parent[index]);
}
return this.parent[index];
}
unite(index1,index2){ //合并
// 拿到他们的丁点坐标
let root1 = this.findSet(index1), root2 = this.findSet(index2)
if(root1 != root2){
// 判断一下各自集合的节点个数,节点少的集合要往节点多的集合上面合并
if(root1 < root2){
[root1,root2] = [root2,root1]
}
// 合并根节点
this.parent[root2] = root1;
// 计算已经合并的节点数量
this.size[root1] += this.size[root2];
this.setCount --;//合并多少,城市数量则减一
}
}
getCount(){
return this.setCount;
}
connected(index1,index2){// 判断两个顶点,是否是一个连通分量
let root1 = this.findSet(index1),root2 = this.findSet(index2);
return root1 == root2;
}
}
至此我们就完成了leetcode-684-冗余连接