[前端]_一起刷leetcode 1319. 连通网络的操作次数

599 阅读3分钟

大家好,我是挨打的阿木木,爱好算法的前端摸鱼老。最近会频繁给大家分享我刷算法题过程中的思路和心得。如果你也是想提高逼格的摸鱼老,欢迎关注我,一起学习。

题目

1319. 连通网络的操作次数

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

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

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

 

示例 1:

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

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

思路

这道题目是一道典型的并查集题目,如果还不清楚什么是并查集的可以先看一下我这篇文章:js中的并查集

  1. 我们先判断一下,要链接n台电脑,最少需要n - 1根网线才能保证全部串接起来,所以如果connections的长度不够n - 1,说明不够链接所有电脑,返回-1
  2. 我们可以通过一轮遍历,判断两台电脑之间是否已经有联系了,如果有的话就重复了,不过这道题目没说不允许重复,我们可以不管它,等到最后不够连通再去拆重复的线即可;
  3. 如果两个元素没有链接过,那么它们就是有效链接,有效链接的数量加一即可,然后把两者建立起关联关系;
  4. 遍历结束的时候,返回n - 1 - 有效链接的数量即可。

实现

/**
 * @param {number} n
 * @param {number[][]} connections
 * @return {number}
 */
var makeConnected = function(n, connections) {
    const len = connections.length;
    // 最少需要n-1根线,如果不够就没法全部连接
    if (n - 1 > len) return -1;

    // 判断有多少个有效链接
    let count = 0;
    const uf = new UnionFind(len);

    for (let i = 0; i < len; i++) {
        let [ a, b ] = connections[i];

        // 如果它们之前已经有联系了,说明是无效链接
        // 否则说明是有效链接,建立关系
        if (uf.find(a) !== uf.find(b)) {
            uf.merge(a, b);
            count++;
        } 
    }

    // 要链接n个元素,只需要n-1个有效链接即可
    return n - 1 - count;
};

class UnionFind {
  constructor(n) {
    // 一开始每个元素的父元素都是自己
    this.parent = new Array(n).fill(0).map((item, index) => index);
  }

  // 找到元素的父元素
  find(index) {
    return this.parent[index] = this.parent[index] === index ? index : this.find(this.parent[index]);
  }

  // 把index2的父元素设置为index1的父元素
  merge(index1, index2) {
    this.parent[this.find(index2)] = this.find(index1);
  }
}

看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。