[路飞]_省份数量

216 阅读3分钟

547. 省份数量

题目

有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。

省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。

给你一个 n x n 的矩阵 isConnected ,其中 isConnected[i][j] = 1 表示第 i 个城市和第 j 个城市直接相连,而 isConnected[i][j] = 0 表示二者不直接相连。

返回矩阵中 省份 的数量。

示例

image.png

输入: isConnected = [[1,1,0],[1,1,0],[0,0,1]]
输出: 2

题解

并查集

并查集

不要问为啥用并查集,因为作者暂时只会用并查集解决这个问题;当然大神可以用DFS和BFS搞定,我不太会,所以此处只讨论使用并查集解决这个问题

什么是并查集
并查集就是将相同类型合并,查询两个已知量是否在一个集合;

合并
将相同类型合并,以本题为例,城市1和城市2相连,得到1和2有关系;将1和2合并;

重点
怎么合并? 以本题为例,isConnected = [[1,1,0],[1,1,0],[0,0,1]]

  • 构建数组list = [0,1,2];这个数组下标表示城市,元素表示与下标城市相连的其他城市。
  • 数组list = [0,1,2]起始时城市0与城市0相连,城市1与城市1相连,城市2与城市2相连;这个可以理解吧
  • i = 0 , j = 0 ,为什么return;因为i = j时,i和j表示的时一座城市,不需要合并。
  • 枚举isConnected,当i = 0 , j = 1时,需要将城市0与城市1连接,将list[0] = list[1];得到list = [1,1,2]。
  • 此时的list = [1,1,2]表示城市0与城市1相连,城市1与城市1相连,城市2与城市2相连;
  • 继续枚举,当i = 1, j = 0时,需要将城市1与城市0连接,这里如何合并呢?
    • j = 0,list[j] = list[0] = 1;这里list[0] = 1表示,城市0与城市1连接,所以继续list[1]与那个城市相连,list[1] = 1,说明list[1]是根节点,不需要再向上寻找
    • i = 1 , list[i] = list[1] = 1;城市1是根节点,不需要再向上寻找
    • list = [1,1,2]
  • 枚举结束
  • 枚举list,对于任意元素k只统计list[k] = k的数量即可得到省份数量
  • 比如list = [1,1,2],只有第2位,第3位list[k] = k
  • 所以isConnected = [[1,1,0],[1,1,0],[0,0,1]]省份为2;

代码

class UnionFind {
  constructor(n) {
    this.node = new Array(n).fill().map((item, idx) => idx)
  }
  // 查找当前元素所在的根节点
  find(x) {
    if (x === this.node[x]) {
      return x
    }
    return this.find(this.node[x])
  }
  // 合并x,y所处集合
  merge(x, y) {
    x = this.find(x)
    y = this.find(y)
    if (x === y) return
    this.node[x] = y
  }
}

var findCircleNum = function (isConnected) {
  const len = isConnected.length
  const unionFind = new UnionFind(len)

  for (let i = 0; i < len; i++) {
    for (let j = 0; j < len; j++) {
      if (isConnected[i][j] === 1) {
        unionFind.merge(i, j)
      }
    }
  }

  let result = 0
  for (let i = 0; i < unionFind.node.length; i++) {
    if (unionFind.node[i] === i) result++
  }
  return result
}

// 0,1,2,3,4,5,6,7,8
var isConnected = [
  [1, 1, 0],
  [1, 1, 0],
  [0, 0, 1],
]
const aa = findCircleNum(isConnected)
console.log(aa)