算法练习帖--63--冗余连接(Java)

冗余连接

一、题目简介

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

输入一个图,该图由一个有着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;

    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值