每日一题算法:2020年9月17日 [冗余连接 II] findRedundantDirectedConnection

2020年9月17日 冗余连接 IIfindRedundantDirectedConnection

在这里插入图片描述

class Solution {
    public int[] findRedundantDirectedConnection(int[][] edges) {

    }
}

解题思路:

先说一说看完之后对题目的理解。

有根树:在有向图中找到一个没有父节点的节点,并且其他节点都只有一个父节点。

这道题的第一步,我们要知道哪一个节点是根节点,这个实际上可能不存在,因为题中规定,删除一条边就能够使有向图变为有根树,那么我们就可以确定,要么是存在根,有一个节点有两个父节点,要么是不存在根节点,是一个有向有环图,环的交点就是存在冲突的点,删除掉后出现的那一条边。

首先考虑第一种情况,存在根,这种情况非常好处理,因为只多了一条边,那么只要找到有哪个节点有两个父节点,删除掉其中一条就可以了。

那么如何确定存在根呢?只需要遍历一遍数组,统计每个节点出现在v位置上的次数,根节点出现0次,重复的节点出现两次,我们只需要把第二次的记录下来就可以了。

那么现在考虑第二种情况,不能确定根节点。

如果不能确定根节点,那么这个有向图必有环,并且根节点会在环上,因为分支必定有一个端点,而终点必须是一个子节点,因为不存在根节点。

此时换上任意一个点都能作为根节点,因为环上的每一个点都只有一个父节点,此时我们只需要找到在最后的那一个在环上的点就可以了。

思路就是这样,感觉这道题还挺简单的,考的是对图的理解吧。不管怎么样,顺着这个思路先做着。

第一部分很简单,第二部分实际实现存在一些问题。虽然我能够找到有向图中环的位置,但是如果要结合哪一个是最后出现的,这就比较麻烦了。

这题没有我想的那么简单,看了一眼解题。

class Solution {
    public int[] findRedundantDirectedConnection(int[][] edges) {
        int nodesCount = edges.length;
        UnionFind uf = new UnionFind(nodesCount + 1);
        int[] parent = new int[nodesCount + 1];
        for (int i = 1; i <= nodesCount; ++i) {
            parent[i] = i;
        }
        int conflict = -1;
        int cycle = -1;
        for (int i = 0; i < nodesCount; ++i) {
            int[] edge = edges[i];
            int node1 = edge[0], node2 = edge[1];
            if (parent[node2] != node2) {
                conflict = i;
            } else {
                parent[node2] = node1;
                if (uf.find(node1) == uf.find(node2)) {
                    cycle = i;
                } else {
                    uf.union(node1, node2);
                }
            }
        }
        if (conflict < 0) {
            int[] redundant = {edges[cycle][0], edges[cycle][1]};
            return redundant;
        } else {
            int[] conflictEdge = edges[conflict];
            if (cycle >= 0) {
                int[] redundant = {parent[conflictEdge[1]], conflictEdge[1]};
                return redundant;
            } else {
                int[] redundant = {conflictEdge[0], conflictEdge[1]};
                return redundant;
            }
        }
    }
}

class UnionFind {
    int[] ancestor;

    public UnionFind(int n) {
        ancestor = new int[n];
        for (int i = 0; i < n; ++i) {
            ancestor[i] = i;
        }
    }

    public void union(int index1, int index2) {
        ancestor[find(index1)] = find(index2);
    }

    public int find(int index) {
        if (ancestor[index] != index) {
            ancestor[index] = find(ancestor[index]);
        }
        return ancestor[index];
    }
}

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/redundant-connection-ii/solution/rong-yu-lian-jie-ii-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值