leetcode | 685. Redundant Connection II (有向图 - 并查集)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mike_learns_to_rock/article/details/88597369

题目

找出有向图中,多余的连接;确保所有点都相连 && 每个节点只有一个parent(不包含root节点);如果有多个solution,去除靠后的连接;【题目保证去除一个连接,就可以满足要求】

Input: [[1,2], [1,3], [2,3]]
Output: [2,3]
Explanation: The given directed graph will be like this:
  1
 / \
v   v
2-->3
Input: [[1,2], [2,3], [3,4], [4,1], [1,5]]
Output: [4,1]
Explanation: The given directed graph will be like this:
5 <- 1 -> 2
     ^    |
     |    v
     4 <- 3

分析

  • 隐含条件:1)只有一个parent,如果一个节点有多个parent(这里是最多两个),肯定除去其中一个连接; 如果有两个parent,优先去除后面出现的连接;除非
1. 第二个连接里面包含了root && root只有一个儿子;
2. 第一个连接不可用,这里不可用的含义是:第一个连接的两个节点循环依赖

答案(后续优化)

class Solution {
    class UnionFind {
        private int union[];
        private int rank[];
        private int size = 0;
        
        public UnionFind(int n) {
            union = new int[n];
            rank = new int[n];
            for (int i = 0; i < n; i++) {
                union[i] = -1;
            }
        }
        
        private int find(int i) {
            while (i != union[i]) i = union[i];
            return i;
        }

        public boolean union(int x, int y) {
            if (union[x] == -1 || union[y] == -1) return false;
            int rootx = find(x);
            int rooty = find(y);
            if (rootx == rooty) return true;
            if (rank[rootx] > rank[rooty]) {
                union[rooty] = rootx;
            } else if (rank[rootx] < rank[rooty]) {
                union[rootx] = rooty;
            } else {
                union[rooty] = rootx;
                rank[rootx]++;
            }
            size--;
            return false;
        }
        
        public void add(int i) {
            if (union[i] == -1) {
                union[i] = i;
                size++;
            }
        }
        
        public int getSize() {
            return size;
        }
    }

       public int[] findRedundantDirectedConnection(int[][] edges) {
       // 记录每个节点的儿子们
        Map<Integer, Set<Integer>> son = new HashMap<>();
        // 记录每个节点的父亲们(正常只有一个)
        Map<Integer, Set<Integer>> parent = new HashMap<>();
        UnionFind uf = new UnionFind(edges.length);
        int resIndex = -1;
        int invalidSon = -1;
        int firstParent = -1;
        int secondParent = -1;

        for (int i = 0; i < edges.length; i++) {
            int x = edges[i][0];
            int y = edges[i][1];
            if (parent.get(y) == null) {
                Set<Integer> set = new HashSet<>();
                set.add(x);
                parent.put(y, set);
            } else {
                Set<Integer> set = parent.get(y);
                for (Integer e : set) {
                    firstParent = e.intValue();
                }
                set.add(x);
                invalidSon = y;
                secondParent = x;
            }

            if (son.get(x) == null) {
                Set<Integer> set = new HashSet<>();
                set.add(y);
                son.put(x, set);
            } else {
                Set<Integer> set = son.get(x);
                set.add(y);
            }
        }

// 这里很重要,判断两个parent的连接,应该去除谁
		if (invalidSon > 0) {
            int[] res = new int[2];
            res[1] = invalidSon;
            int firstGrandParent = 0;
            
            Set<Integer> set = parent.get(firstParent);
           if (set != null) {
                for (Integer e : set) {
                    firstGrandParent = e.intValue();
                }
            }

            if ((son.get(secondParent).size() == 1 && parent.get(secondParent) == null)
                    || (firstGrandParent == invalidSon)) {
                res[0] = firstParent;
            } else{
                res[0] = secondParent;
            }
            return res;

        }

// 如果没有两个parent的情况,那么连通图中,找出多余连接
        for (int i = 0; i < edges.length; i++) {
            int x = edges[i][0];
            int y = edges[i][1];

            uf.add(x - 1);
            uf.add(y - 1);
            if (uf.union(x - 1, y - 1)) {
                resIndex = i;
            }
        }
        return edges[resIndex];
    }
}

猜你喜欢

转载自blog.csdn.net/mike_learns_to_rock/article/details/88597369