当前位置 博文首页 > Inmaturity_7的博客:算法练习帖--63--冗余连接(Java)

    Inmaturity_7的博客:算法练习帖--63--冗余连接(Java)

    作者:[db:作者] 时间:2021-07-16 21:50

    冗余连接

    一、题目简介

    在本问题中, 树指的是一个连通且无环的无向图。

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

    结果图是一个以边组成的二维数组。每一个边的元素是一对[u, v] ,满足 u < v,表示连接顶点u 和v的无向图的边。

    返回一条可以删去的边,使得结果图是一个有着N个节点的树。如果有多个答案,则返回二维数组中最后出现的边。答案边 [u, v] 应满足相同的格式 u < v。
    (题目来源:力扣(LeetCode))

    示例 1:
    输入: [[1,2], [1,3], [2,3]]
    输出: [2,3]
    解释: 给定的无向图为:
        1
       / \
      2 - 3
    
    示例 2:
    输入: [[1,2], [2,3], [3,4], [1,4], [1,5]]
    输出: [1,4]
    解释: 给定的无向图为:
    5 - 1 - 2
        |   |
        4 - 3
    
    注意:
    输入的二维数组大小在 3 到 1000。
    二维数组中的整数在1到N之间,其中N是输入数组的大小。
    

    二、解决方法

    1. 并查集

    package com.lxf.bcj;
    
    public class FindRedundantConnection {
            int[] parent;//父结点数组
    
            public int[] findRedundantConnection(int[][] edges) {
                int N=edges.length;//结点数
                parent=new int[N+1];//空出0,让结点值直接对应数组下标
                for (int i = 1; i <= N; i++) {
                    parent[i]=i;//父结点数组初始化
                }
                for (int[] edge : edges) {
                    if(find(edge[0])!=find(edge[1])){
                        //如果两个点的父节点不相同,直接合并
                        union(edge[0],edge[1]);
                    }else{
                        //如果两个点的父节点相同,说明当前两个结点相连后图成环
                        return edge;
                    }
                }
                return new int[0];
            }
    
            /**
             * 查找当前结点的父结点方法
             * @param index
             * @return
             */
            public int find(int index){
                while(index!=parent[index]){
                    parent[index]=parent[parent[index]];
                    index=parent[index];
                }
                return index;
            }
    
            /**
             * 合并集合
             * @param index1
             * @param index2
             */
            public void union(int index1,int index2){
                parent[find(index2)]=find(index1);
            }
    }
    
    

    2.BFS(深度优先遍历算法)

    题解区大佬方法:Java DFS/拓扑排序/并查集 实现

    package com.lxf.bcj;
    
    import java.util.HashSet;
    import java.util.Set;
    
    public class FindRedundantConnection {
        public int[] findRedundantConnection(int[][] edges) {
            // 树指的是一个连通且无环的无向图。
            int len = edges.length;
            //新建一个HashSet数组
            Set<Integer>[] map = new HashSet[len + 1];
            for(int[] edge: edges){
                if(map[edge[0]] == null){
                    map[edge[0]] = new HashSet<>();
                }
                //第一个顶点下标对应的HashSet集合存储对应第二个顶点
                map[edge[0]].add(edge[1]);
    
                if(map[edge[1]] == null){
                    map[edge[1]] = new HashSet<>();
                }
                //第二个顶点下标对应的HashSet集合存储对应第一个顶点
                map[edge[1]].add(edge[0]);
            }
    
            for(int i = len - 1; i >= 0; i--){
                //移除当前两个顶点
                map[edges[i][0]].remove(edges[i][1]);
                map[edges[i][1]].remove(edges[i][0]);
                //记录顶点是否已经遍历过
                boolean[] used = new boolean[len + 1];
                if(dfs(map, edges[i][1], edges[i][0], used)){
                    //如果这两个顶点还能连通,说明已经成环,返回这两个顶点
                    if(edges[i][1] < edges[i][0]){
                        return new int[]{edges[i][1], edges[i][0]};
                    }else{
                        return new int[]{edges[i][0], edges[i][1]};
                    }
                }
            }
            return new int[0];
        }
    
        private boolean dfs(Set<Integer>[] map, int x, int y, boolean[] used){
            //如果两个顶点相等,说明可以连通
            if(x == y){
                return true;
            }
            used[x] = true;//当前顶点已经遍历
            for(int i: map[x]){
                //遍历这个顶点对应的所有未遍历过的顶点
                if(!used[i]){
                    if(dfs(map, i, y, used)){//递归操作
                        return true;
                    }
                }
            }
            return false;
    
        }
    }
    
    
    cs