LeetCode(1319):连通网络的操作次数 Number of Operations to Make Network Connected(Java)

234 篇文章 1 订阅
177 篇文章 0 订阅

2021.1.8 LeetCode 从零单刷个人笔记整理(持续更新)

github:https://github.com/ChopinXBP/LeetCode-Babel

这是一道经典的并查集问题。

关键点在于:每一个多余的连通集都需要一次操作进行消除,每一次操作需要一条多余的边。

因此,可以先建立一个并查集,初始连通集个数为n。根据给定的connection来合并连通集,每一次失败的合并意味着有一条多余的边。

计算多余的连通集个数result。

如果result=0,说明已经全连通,直接返回0;

如果leftEdge < result,说明多余的边不足以补齐完整连通集,返回-1;

否则返回result。


传送门:连通网络的操作次数

There are n computers numbered from 0 to n-1 connected by ethernet cables connections forming a network where connections[i] = [a, b] represents a connection between computers a and b. Any computer can reach any other computer directly or indirectly through the network.

Given an initial computer network connections. You can extract certain cables between two directly connected computers, and place them between any pair of disconnected computers to make them directly connected. Return the minimum number of times you need to do this in order to make all the computers connected. If it’s not possible, return -1.

用以太网线缆将 n 台计算机连接成一个网络,计算机的编号从 0 到 n-1。线缆用 connections 表示,其中 connections[i] = [a, b] 连接了计算机 a 和 b。

网络中的任何一台计算机都可以通过网络直接或者间接访问同一个网络中其他任意一台计算机。

给你这个计算机网络的初始布线 connections,你可以拔开任意两台直连计算机之间的线缆,并用它连接一对未直连的计算机。请你计算并返回使所有计算机都连通所需的最少操作次数。如果不可能,则返回 -1 。

示例 1:
输入:n = 4, connections = [[0,1],[0,2],[1,2]]
输出:1
解释:拔下计算机 1 和 2 之间的线缆,并将它插到计算机 1 和 3 上。

示例 2:
输入:n = 6, connections = [[0,1],[0,2],[0,3],[1,2],[1,3]]
输出:2

示例 3:
输入:n = 6, connections = [[0,1],[0,2],[0,3],[1,2]]
输出:-1
解释:线缆数量不足。

示例 4:
输入:n = 5, connections = [[0,1],[0,2],[3,4],[2,3]]
输出:0
 

提示:
1 <= n <= 10^5
1 <= connections.length <= min(n*(n-1)/2, 10^5)
connections[i].length == 2
0 <= connections[i][0], connections[i][1] < n
connections[i][0] != connections[i][1]
没有重复的连接。
两台计算机不会通过多条线缆连接。


package Problems;

/**
 * There are n computers numbered from 0 to n-1 connected by ethernet cables connections forming a network where connections[i] = [a, b] represents a connection between computers a and b.
 * Any computer can reach any other computer directly or indirectly through the network.
 * Given an initial computer network connections. You can extract certain cables between two directly connected computers,
 * and place them between any pair of disconnected computers to make them directly connected. Return the minimum number of times you need to do this in order to
 * make all the computers connected. If it's not possible, return -1.
 * 用以太网线缆将 n 台计算机连接成一个网络,计算机的编号从 0 到 n-1。线缆用 connections 表示,其中 connections[i] = [a, b] 连接了计算机 a 和 b。
 * 网络中的任何一台计算机都可以通过网络直接或者间接访问同一个网络中其他任意一台计算机。
 * 给你这个计算机网络的初始布线 connections,你可以拔开任意两台直连计算机之间的线缆,并用它连接一对未直连的计算机。请你计算并返回使所有计算机都连通所需的最少操作次数。如果不可能,则返回 -1 。
 */

public class NumberOfOperationsToMakeNetworkConnected {
    //并查集
    private class UnionFind {
        //父亲结点标识数组
        private int[] parent;
        //连通集个数
        private int count;

        //初始化并查集,所有节点的祖先均为其本身。连通集初始个数为n
        public UnionFind(int n) {
            count = n;
            parent = new int[n];
            for (int i = 0; i < n; i++) {
                parent[i] = i;
            }
        }

        //find用于查找x节点的祖先节点(祖先节点的特征为x=parent[x])
        public int find(int x) {
            while (x != parent[x]) {
                // 路径压缩(隔代压缩)
                parent[x] = parent[parent[x]];
                x = parent[x];
            }
            return x;
        }

        //合并x和y。如果 x 和 y 本来就在一个连通分量里,返回 false;否则合并x和y,连通集个数-1。
        public boolean union(int x, int y) {
            int rootX = find(x);
            int rootY = find(y);

            if (rootX == rootY) {
                return false;
            }

            parent[rootX] = rootY;
            count--;
            return true;
        }
    }

    public int makeConnected(int n, int[][] connections) {
        // 建立并查集,每一个多余的连通集都需要一次操作进行消除,每一次操作需要一条多余的边。
        UnionFind unionFind = new UnionFind(n);

        // 计算多余的边的数量,每次失败的合并意味着有一条多余的边。
        int leftEdge = 0;
        for (int[] connection : connections) {
            boolean success = unionFind.union(connection[0], connection[1]);
            if (!success) {
                leftEdge++;
            }
        }

        // 计算多余的连通集个数result。
        // 如果result=0,说明已经全连通,直接返回0;如果leftEdge<result,说明多余的边不足以补齐完整连通集,返回-1。否则返回result。
        int result = unionFind.count - 1;
        return result == 0 ? 0 : (leftEdge < result ? -1 : result);
    }
}




#Coding一小时,Copying一秒钟。留个言点个赞呗,谢谢你#

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值