【LeetCode】547.省份数量(Number of Provinces)

本文针对LeetCode上的省份数量问题提供了解决方案。通过构建图模型,利用并查集算法找出图中连通块的数量,即省份的数量。介绍了算法的具体实现步骤及代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

There are n cities. Some of them are connected, while some are not. If city a is connected directly with city b, and city b is connected directly with city c, then city a is connected indirectly with city c.

A province is a group of directly or indirectly connected cities and no other cities outside of the group.

You are given an n x n matrix isConnected where isConnected[i][j] = 1 if the ith city and the jth city are directly connected, and isConnected[i][j] = 0 otherwise.

Return the total number of provinces.

Example 1:

Input:isConnected = [[1,1,0],[1,1,0],[0,0,1]]
Output:2

Example 2:

Input:isConnected = [[1,0,0],[0,1,0],[0,0,1]]
Output:3

Constraints:

  • 1 <= n <= 200
  • n == isConnected.length
  • n == isConnected[i].length
  • isConnected[i][j] is 1 or 0
  • isConnected[i][i] == 1
  • isConnected[i][j] == isConnected[j][i]

题目来源:https://leetcode-cn.com/problems/number-of-provinces/

题目大意

输入一个二维数组isConnected,若isConnected[i][j] = 1表明第 i i i个城市和第 j j j个城市是直接相连的,若isConnected[i][j] = 0表明第 i i i个城市和第 j j j个城市不是直接相连的。所有直接相连或间接相连的城市构成一个省,题目要求我们返回输入中省的数量。

解题方法

方法一:并查集

思路
根据本题题意,对于输入的 n × n n \times n n×n二维矩阵isConnected,可构建出如下的图模型:

  • 将每座城市看作图中的一个节点,分别用编号 0 , ⋯   , n − 1 0,\cdots,n - 1 0,,n1来表示;
  • 如果isConnected[i][j] = 1,则表明编号为 i i i j j j的节点之间存在一条无向边,无权值;
  • 题目要求我们求解的省份数量,其实就是找出图中连通块的数量。

基于上述建立的图模型,本题可以用并查集来求解,而且可以直接套用朴素并查集的模板。编号 0 , ⋯   , n − 1 0,\cdots,n - 1 0,,n1代表 n n n个节点,使用一维数组 p p p来存储并对这些节点进行初始化,然后遍历二维数组isConnected中的每个元素,isConnected[i][j] = 1则合并编号为 i i i j j j的节点,最后,统计数组 p p p中满足 p [ x ] = = x p[x] == x p[x]==x 的个数并返回。并查集中只有根节点才会满足 p [ x ] = = x p[x] == x p[x]==x这一等式,根节点的个数就代表图中连通块的数量

代码

class Solution {
    int[] p;

    public int find(int x){
        if(p[x] != x) p[x] = find(p[x]);
        return p[x];
    }

    public void union(int x, int y){
        p[find(x)] = find(y);
    }

    public int findCircleNum(int[][] isConnected) {
        int n = isConnected.length;
        p = new int[n];
        for(int i = 0; i < n; i ++) p[i] = i;

        for(int i = 0; i < n; i ++){
            for(int j = 0; j < n; j ++){
                if(i != j && isConnected[i][j] == 1) union(i, j);
            }
        }

        int res = 0;
        for(int i = 0; i < n; i ++){
            if(p[i] == i) res ++;
        }
        return res;
    }
}

复杂度分析

  • 时间复杂度: O ( n 2 l o g n ) O(n^2logn) O(n2logn),其中 n n n为节点(或城市)的数量,需要遍历isConnected中的所有元素,时间复杂度是 O ( n 2 ) O(n^2) O(n2),使用了路径压缩后,并查集操作的最坏时间复杂度是 O ( l o g n ) O(logn) O(logn)(平均情况下的时间复杂度是 O ( α ( n ) ) O(\alpha(n)) O(α(n)),其中 α ( n ) \alpha(n) α(n)是一个很小的常数),因此总时间复杂度是 O ( n 2 l o g n ) O(n^2logn) O(n2logn)
  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n为节点(或城市)的数量,需要使用一维数组 p p p来存储每个节点的父节点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值