[路飞] 冗余连接 ii

67 阅读2分钟

记录 1 道算法题

冗余连接 ii

685. 冗余连接 II - 力扣(LeetCode) (leetcode-cn.com)


从一个根节点出发连接子节点,在连接中添加一个边,这条边会造成环或者冲突,冲突指子节点存在两个父节点。找出这条边,并返回。

自身是一个满足树状结构的连接,那么多出来的边要么是子节点指向其他子节点或者指向根节点。当指向根节点的时候一定会形成一个环。删除形成环的边就可以。当指向其他节点的时候,可能会指向一个有父元素的节点,同时也可能形成一个环。比如下面这张图,[3,5] 形成了一个环,并且让 3 有了两个父节点。这时候要先处理形成父节点的边。一般来说添加一条边,环和冲突只会出现一个,当同时出现的时候,优先解决冲突。而且要解决形成环的那个冲突。

首先让边进行连线。将冲突的边和形成环的边记录下来。使用并查集进行连接,这样能找到形成冲突的在环内的边。由于是树状结构,有明确的父节点,所以不能使用路径压缩,于是还需要有一个数组来记录实际画上的连接。

有 n 个节点就有 n - 1 条边。

    function findRedundantDirectedConnection(edges) {
        const n = edges.length
        
        const parent = Array.from(new Array(n + 1), (_, i) => i)
        const link = Array.from(new Array(n + 1), (_, i) => i)
        
        let conflict,circle
        for(let i = 0; i < n; i++) {
            const [a, b] = edges[i]
            
            let pIdx = link[b]
            // 如果有两个父节点
            // 没有冲突就有环
            if (child !== b) {
                conflict = pIdx
            } else {
                // 连接
                link[b] = a
                // 比较并查集根节点
                pIdx = find(parent, a)
                const childIdx = find(parent, b)
                if (pIdx === childIdx) {
                    circle = i
                } else {
                    // 并入
                    parent[childIdx] = pIdx
                }
            }
        }
        
        if (conflict === undefined) {
            // 只有冲突的时候,去掉环就可以
            return edges[circle]
        } else {
            // 有环又有冲突的时候,还要再判断
            if (circle === undefined) {
                return edges[conflict]
            } else {
                // 又有环又有冲突的时候,
                // 要找在环内的造成冲突的边,
                // 即从子节点,找连接他的两个父节点的边,
                // 哪一条边在环内。
                // 如果冲突了就不会进行 link,所以当冲突的边在环内的时候,
                // 一定是已经 link 造成的,所以可以直接 link[b],找到那个父节点。
                const [a, b] = edges[conflict]
                return [link[b], b]
            }
        }
    }
    
    function find(parent, i) {
        if (parent[i] !== i) {
            parent[i] = find(parent, parent[i])
        }
        
        return parent[i]
    }