[路飞]_省份数量

410 阅读3分钟

「这是我参与2022首次更文挑战的第29天,活动详情查看:2022首次更文挑战

leetcode-547 城市数量

题目介绍

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

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

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

返回矩阵中 省份 的数量。

示例1

image.png

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

示例2

image.png

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

提示:

  • 1 <= n <= 200
  • n == isConnected.length
  • n == isConnected[i].length
  • isConnected[i][j]10
  • isConnected[i][i] == 1
  • isConnected[i][j] == isConnected[j][i]

解题思路

这道题求省份的数量,其实就是要把所有相连的城市都连接起来形成一个集合,最后看看总共有几个不相连的集合就是有多少个省份

说明一下一些特殊点的意义:

  • isConnected[i][i] 代表的是城市本身与自己相连,所以必定是 1
  • isConnected[i][j]isConnected[j][i] 分别代表城市 i 与城市 j 相连和城市 j 与城市 i 相连,因为城市之间的连通是相互的,所以这两个值必定是一致的,在进行城市连接的时候,只需要判断其中一个就可以了

这道题非常适合使用并查集来解决,并查集就是把其中有关联的数据连通,然后能够查找非连通数量的数据结构

解题步骤

  1. 创建一个大小为城市数量的并查集
  2. 遍历 isConnected 二维数组,每一个子数组只需要遍历 isConnected[i][0]isConnected[i][i - 1] 即可,因为 isConnected[i][i] 表示的是自己,无需判断,而 isConnected[i][i + 1] 之后的值未来还会再遍历到一次,所以只需遍历一次就好(例如: isConnected[1][2] 表示的含义与 isConnected[2][1] 表示的含义是相同的,只需要遍历 isConnected[2][1] 就行)
  3. 如果 isConnected[i][j] === 1,则把 ij 这两个城市相连
  4. 最后再次遍历所有的城市,判断有多少个省份

解题代码

var findCircleNum = function(isConnected) {
    const len = isConnected.length
    const unionSet = new UnionSet(len)
    for (let i = 0; i < len; i++) {
        for (let j = 0; j < i; j++) {
            if (isConnected[i][j] === 1) unionSet.merge(i, j)
        }
    }
    let sum = 0
    for (let i = 0; i < len; i++) {
        if (unionSet.find(i) === i) sum++
    }
    return sum
};

// 并查集
class UnionSet {
    constructor(n) {
        this.fa = []
        this.size = []
        for (let i = 0; i < n; i++) {
            this.fa[i] = i
            this.size[i] = 1
        }
    }

    find(i) {
        if (this.fa[i] === i) return i
        // 路径压缩
        const root = this.find(this.fa[i])
        this.fa[i] = root
        return root
    }

    merge(a, b) {
        const fa = this.find(a), fb = this.find(b)
        if (fa === fb) return
        // 按秩优化
        if (this.size[a] < this.size[b]) {
            this.fa[fa] = fb
            this.size[fb] += this.size[fa]
        } else {
            this.fa[fb] = fa
            this.size[fa] += this.size[fb]
        }
    }
}

不了解并查集这种数据结构的,可以阅读 并查集,解决连通问题的利器