685.冗余连接
685.冗余连接
4:03
// 定义并查集类
class UnionFind{
    // 构造函数初始化并查集
    constructor(n){
        this.parent = new Array(n).fill(0).map((item,index)=>index)
        this.rank = new Array(n).fill(1)
        this.count = n
    }
    // 查找元素的根节点
    find(x){
        if(this.parent[x] !== x){
            this.parent[x] = this.find(this.parent[x])
        }
        return this.parent[x]
    }
    // 合并两个集合
    union(x,y){
        let rootX = this.find(x)
        let rootY = this.find(y)
        if(rootX === rootY){
            return false
        }
        if(this.rank[rootX] < this.rank[rootY]){
            this.parent[rootX] = rootY
            this.rank[rootY] += this.rank[rootX]
        }else{
            this.parent[rootY] = rootX
            this.rank[rootX] += this.rank[rootY]
        }
        this.count--
    }
    // 判断两个元素是否属于同一个集合
    connected(x,y){
        return this.find(x) === this.find(y)
    }
    // 获取集合的数量
    getCount(){
        return this.count
    }
}
/**
 * @param {number[][]} edges
 * @return {number[]}
 */
// 考虑三种情况:
// 1.附加边指向了我们的根结点,导致所有的节点都有一个父节点,导致出现环;
// 2.附加边没有指向我们根节点,会出现树中某个节点会有两个父亲节点;也有可能会出现环路;
var findRedundantDirectedConnection = function(edges) {
    // 先要获取节点的个数,就是边的个数
    let nodeCount = edges.length
    // 根据节点的个数构造并查集,长度加1,避免从0开始
    let uf = new UnionFind(nodeCount + 1)
    //怎么记录产生了两个父节点
    let parent=[] //记录每一个节点的父节点是多少
    for(let i=1;i<(nodeCount+1);i++){//边的长度+1
        parent[i] = i//初始化
    }
    let conflit = -1 //记录产生两个父节点的边
    let cycle = -1 //记录产生环路的边
    for(i in edges){
        let edge=edges[i];
        let node1=edge[0],node2=edge[1];//拿到了两个节点
        if(parent[node2] != node2){//node2这个节点有两个父节点
            conflit = i;//记录产生两个父节点的边
        }else{//否则没有双重父节点,就把他们连起来
            parent[node2] = node1;
            if(uf.find(node1) == uf.find(node2)){//如果两个节点的根节点相同,说明产生了环路
                cycle = i;//记录产生环路的边
            }else{//既有环路,又有双重节点
                uf.union(node1,node2);//把两个节点连起来
            }
        }
    }
    if(conflit < 0){//没有双重父节点产生,就把环路记录下来
        return edges[cycle];//返回产生环路的边
    }else{//只有双重父节点产生
        let conflitEdge = edges[conflit];//拿到产生双重父节点的边
        if(cycle >= 0){//既有环路,又有双重节点
            return [parent[conflitEdge[1]],conflitEdge[1]];//有两个入度点
        }else{
            return conflitEdge;//只有一个入度点
        }
    }
};

                
            
        
浙公网安备 33010602011771号