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一秒钟。留个言点个赞呗,谢谢你#