【路飞】算法与数据结构-连通网络的操作次数

109 阅读2分钟

不管全世界所有人怎么说,我都认为自己的感受才是正确的。无论别人怎么看,我绝不打乱自己的节奏。喜欢的事自然可以坚持,不喜欢的怎么也长久不了。

LeetCode:原题地址

题目要求

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

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

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

示例 1:

sample_1_1677.png

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

示例 2:

sample_2_1677.png

输入: 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]
  • 没有重复的连接。
  • 两台计算机不会通过多条线缆连接。

思路

  • n个电脑连接起来,最少需要n-1个网线
  • 也就是如果网线的数量connections.length小于n-1,那么肯定是链接不起来的。
  • 把连通分量合并之后,假设有X个连通域,那么把X个连通域链接起来需要的网线数量不就是要求的网线数量吗?
/**
 * @param {number} n
 * @param {number[][]} connections
 * @return {number}
 */
class UnionFindCollect {
  constructor(n) {
    this.parent = new Array(n).fill(0).map((cur, index) => index);
    this.size = n;
  }

  find(x) {
    if (x !== this.parent[x]) {
      this.parent[x] = this.find(this.parent[x]);
    }
    return this.parent[x];
  }

  union(x, y) {
    const rootX = this.find(x);
    const rootY = this.find(y);
    if (rootX !== rootY) {
      this.parent[rootY] = rootX;
      this.size--;
    }
  }
}
const makeConnected = (n, connections)=> {
  //n个电脑最少需要n-1个网线,也就是当网线数量小于n-1的时候是链接不成功的
  if (connections.length < n - 1) return -1;
  const uf = new UnionFindCollect(n);
  //利用并查集模板合并连通分量
  //ps:这个月一直在并查集,默认大家会写并查集模板
  for(let [x,y] of connections){
    uf.union(x, y)
  }
  //返回连通域的数量unionSize
  const unionSize = uf.size;
  //最后只需要保留一个连通域(把所有的电脑都连通),所以需要把所有的连通域都链接起来
  //链接unionSize个连通域需要的最少网线数量为unionSize-1
  return unionSize - 1;
};