547.省份数量

104 阅读2分钟

题目

Leetcode链接

有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。给你一个 n x n 的矩阵 isConnected ,其中 isConnected[i][j] = 1 表示第 i 个城市和第 j 个城市直接相连,而 isConnected[i][j] = 0 表示二者不直接相连。请返回矩阵中 省份 的数量。

示例1

  • isConnected = [[1,1,0],[1,1,0],[0,0,1]]
  • 2

示例2

  • isConnected = [[1,0,0],[0,1,0],[0,0,1]]
  • 3

提示

  • 1 <= n <= 200
  • n == isConnected.length
  • n == isConnected[i].length
  • isConnected[i][j] 为 1 或 0
  • isConnected[i][i] == 1
  • isConnected[i][j] == isConnected[j][i]

题解

分析:这个问题是一个典型的图论问题,可以通过并查集数据结构来解决。问题的目的是找出图中的连通分量数量,每个连通分量代表一个省份。

并查集:是一种数据结构,用于处理一些涉及集合元素的合并及查询问题,特别适用于解决一些不交集的合并和查找问题。以下是并查集的应用场景:

  1. 网络连通:在网络中判断两个节点是否连通。
  2. 任务调度:可以用于管理任务分组和分配。
  3. 动态连通:在动态变化的环境中,需要频繁地合并和查询集合的连通性。

代码

class Solution {
    public int[] set;

    // init(int n):初始化并查集
    public void init(int n) {
        set = new int[n];
        for (int i = 0; i < n; i++) {
            set[i] = i;
        }
    }

    // find(int x):确定 x 属于哪个子集
    public int find(int x) {
        return x == set[x] ? x : (set[x] = find(set[x]));
    }

    // union(int x, int y):合并 x 和 y 为一个子集
    public void union(int x, int y) {
        set[find(x)] = find(y);
    }

    public int findCircleNum(int[][] isConnected) {
        int len = isConnected.length, count = 0;
        // 1. 初始化并查集
        init(len);
        // 2. 将连接的省份进行合并,由于是无向图,所以考虑一半即可
        for (int i = 0; i < len; i++) {
            for (int j = i + 1; j < len; j++) {
                if (isConnected[i][j] == 1) {
                    union(i, j);
                }
            }
        }
        // 3. 计算省份数量
        for (int i = 0; i < len; i++) {
            if (set[i] == i) count++;
        }
        return count;
    }
}