【路飞】算法与数据结构-冗余连接 II

111 阅读1分钟

不管全世界所有人怎么说,我都认为自己的感受才是正确的。无论别人怎么看,我绝不打乱自己的节奏。喜欢的事自然可以坚持,不喜欢的怎么也长久不了。

LeetCode:原题地址

题目要求

在本问题中,有根树指满足以下条件的 有向 图。该树只有一个根节点,所有其他节点都是该根节点的后继。该树除了根节点之外的每一个节点都有且只有一个父节点,而根节点没有父节点。

输入一个有向图,该图由一个有着 n 个节点(节点值不重复,从 1 到 n)的树及一条附加的有向边构成。附加的边包含在 1 到 n 中的两个不同顶点间,这条附加的边不属于树中已存在的边。

结果图是一个以边组成的二维数组 edges 。 每个元素是一对 [ui, vi],用以表示 有向 图中连接顶点 ui 和顶点 vi 的边,其中 ui 是 vi 的一个父节点。

返回一条能删除的边,使得剩下的图是有 n 个节点的有根树。若有多个答案,返回最后出现在给定二维数组的答案。

示例 1:

graph1.jpg

输入: edges = [[1,2],[1,3],[2,3]]
输出: [2,3]

示例 2:

输入: edges = [[1,2],[2,3],[3,4],[4,1],[1,5]]
输出: [4,1]

graph2.jpg 提示:

  • n == edges.length
  • 3 <= n <= 1000
  • edges[i].length == 2
  • 1 <= ui, vi <= n

思路

利用并查集,先查出入度为2的点和边 再删除这些边判断能否生成树(如果删除边后两个点根节点不一样就不能生成树)
如果没有入度为2的点就去判断生成环路的边删除

/**
 * @param {number[][]} edges
 * @return {number[]}
 */
var findRedundantDirectedConnection = function(edges) {
    let inDegree = []; // 记录节点入度
    let vec = [] // 记录边
    let un = new UnionFind(edges.length)

    for(let i = 0; i <= edges.length;i++) {
        inDegree[i] = 0
    }
    for (let i = 0; i < edges.length; i++) {
        inDegree[edges[i][1]]++; // 统计入度
    }
     for (let i = edges.length - 1; i >= 0; i--) {
            if (inDegree[edges[i][1]] == 2) {
                vec.push(edges[i]);
            }
    }
    if(vec.length) {
        // 删除入度为2的边
        if(isTreeAfterRemoveEdge(edges,vec[0])) {
            return vec[0]
        }
        return vec[1]
    } else {
        // 判断环路
        for(let i = 0; i < edges.length;i++){
            if(un.union(edges[i][0],edges[i][1])) {
                return edges[i]
            }
        }
    }

    function isTreeAfterRemoveEdge(edges, deleteEdge) {
        for(let i = 0; i < edges.length;i++){
            if(edges[i] == deleteEdge) continue;
            un.union(edges[i][0],edges[i][1])
        }
        if(un.find(deleteEdge[0]) == un.find(deleteEdge[1])) {
            return true
        }
        return false
    }
};

class UnionFind{
    constructor(n){
        this.rank = []
        this.parent = []
        for(let i = 0;i<=n;i++){
            this.parent[i] = i;
            this.rank[i] = 0;
        }
    }

    find(index){
        if(this.parent[index] != index){
            this.parent[index] = this.find(this.parent[index]);
        }
        return this.parent[index];
    }

    union(x,y){
        let x_root = this.find(x)
        let y_root = this.find(y)
        if(x_root == y_root) {
          return [x,y]
        }else {
          if(this.rank[x_root]>this.rank[y_root]) {
              this.parent[y_root] = x_root
          }else if(this.rank[x_root]<this.rank[y_root]){
             this.parent[x_root] = y_root 
          }else {
            this.parent[x_root] = y_root
            this.rank[y_root]++
          }
        }
    }
}