看啥推荐读物
专栏名称: Taec0123
目录
相关文章推荐
今天看啥  ›  专栏  ›  Taec0123

2021/01/23 每日一题 连通网络的操作次数

Taec0123  · 简书  ·  · 2021-01-24 10:41

LeetCode上 连通网络的操作次数 ,并查集题目again,记录下解题思路

假设现在传入 n = 6, connections = [[0,1],[0,2],[0,3],[1,2],[1,3]] ,有6个节点和5根网线,这里需要确认一个问题,如果网线数量小于节点数-1的数量,那么无论如何都无法连通,那么 connections.length < n - 1 根据题意就会返回-1
根据传入的参数可以画出如下的关系图,会分为[0,1,2,3] [4] [5]三个区域,这3个区域相连需要2条网线,即[0,1,2,3]中多余的两条


根据题意,每两台计算机最多一条线连接且没有重复连接,这里想到并查集,创建n个节点,先是循环 connections = [[0,1],[0,2],[0,3],[1,2],[1,3]] 把每个子数组两点之间先连接起来,即把后一个的 parent 属性设为前一个,之后每次连接都判断两个节点的最顶端父节点是否相同,如果相同那就跳过连接,最后就能把连接图简化成下图所示, [1,2],[1,3] 就是多余的网线,用多出来的两条线用于连接[0,5] [0,4]即可

那么最后需要移动的结果就是能分成几个块,即几个元素的父节点是自己本身,然后用这个数-1得到的值就是最后所求结果

// 定义一个节点
class node {
   constructor (i) {
     // 将自己的父亲设为自己 
     this.parent = this
     // val属性记录下当前节点在accounts中的位置
     this.val = i
   }
}
// 定义查找函数,不断查找父节点,直到父节点等于本身
const find = function (x) {
   while(x !== x.parent) {
      x = x.parent
   }
   return x 
}
var makeConnected = function(n, connections) {
  // 保存connections的长度,即有多少条线
  let len = connections.length
  // 创建n的节点数组
  let nodes = Array(n).fill(0).map((x,i) => new node(i))
  // 需要移动几条线
  let res = 0
  if(len < n-1) return res - 1
  // 遍历循环connections数组,用里面的子数组进行数据连接
  for(let i = 0; i < len; i++) {
     let [x,y] = connections[i]
     
     if(find(nodes[x]) !== find(nodes[y])) {
        // 如果对应的子数组里面的两个节点的父元素不相同,就连接两个元素
        find(nodes[y]).parent = find(nodes[x])
     }
  }
  // 然后需要查询连接完成之后,nodes数组中有几个分块,即有几个元素父元素等于本身
  for(let j = 0; j < nodes.length; j++) {
     if(find(nodes[j]) === nodes[j]) {
        // 如果当前节点的父元素等于本身,即计算有多少个需要连接的点
        res++
     }
  }
  return res - 1
};



原文地址:访问原文地址
快照地址: 访问文章快照