【LeetCode】LeetCode 547. 省份数量(Java版 什么是并查集)

news2024/12/23 17:40:03

427ef4152dbf4b6c92618a198935cb6c.png

  📝个人主页:哈__

期待您的关注 

1b7335aca73b41609b7f05d1d366f476.gif

一、题目描述

 

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

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

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

返回矩阵中 省份 的数量。

06fb37df43c1402bac08cb1b3a8644e7.png

a3569267761647129e2c156a424fc7dd.png 

二、思路讲解 

这是一道有关图的算法题目,题目当中给出了这样的描述:共有n个城市,其中的一些彼此相连,一些没有连接,如果a与b相连并且b与c相连,那么a与c也相连,这不就是连通性嘛。在看看这道题让求的是什么,求的是省份的数量,而一个省份内的地点之间都是连通的,题目让我们返回省份的值。我们的目标就是把每一个地区分到一个省份当中。

在这里我要给大家先讲解一种概念“并查集”。

什么是并查集?在我看来就是将图中的结点进行分类的操作,“并”就是将两个结点分类到一起,“查”就是查找结点到底是属于哪个类的。

这样子的描述不够清晰,我引入这样的一个例子。

我在以前看电视剧的时候,总是会有双方交战的场景,我当时就在想,他们的双方是如何分清谁是谁的,难道不会打错人吗?青青草原的绿草已经被羊羊们吃光了,羊羊们为了争夺资源开始了内战,在某一天喜羊羊带领着“喜门”大军去占领一片新的草原,沸羊羊带领着“沸门”大军也去争夺这片草原。两军在小路交叉口遇见。

7bbfa7b329e64112a52c8f06c2f3f152.png

 这次对决的双方羊数很多,假定羊都是白色的,无法区分,我们强制在两只羊交战之前都要自报家门,如果这两只羊是一个阵营的那么就不交战,那么该如何自报家门呢?乐羊羊问道:“你是哪一个阵营的,你阵营的首领是谁”。哈羊羊说道:“我是喜门的,我的首领是谁我忘了,不过我知道我的上层是谁,让我问问我的上层首领是谁”。于是哈羊羊问了他的上层,他的上层又问了上层,最后通知到了喜羊羊这里,喜羊羊又往下通报确认哈羊羊的身份,最后乐羊羊确认了哈羊羊的身份,并且把哈羊羊当作是自己人。

61e4c19474f04a8a958f04c7b53ef728.png

 喜羊羊和沸羊羊大战一场,突然一条情报传入到他们的耳中:“报告门主,美门门主美羊羊被灰太狼抓走了,请求支援!”喜羊羊和沸羊羊一听,立感不妙,现在不是内战的时候,要去救援美羊羊,为了防止内战,于是两羊商量,决定选出一羊作为另一只羊的上层,这样喜门和沸门就完成了合并过程,双方的羊在交战前再次询问上层的时候,都会是喜羊羊或者沸羊羊。

这就是一个简单的“查”和“并”的过程。并查集的关键就是这两个过程。

定义以下的find函数。p是一个数组,用于记录每一个人的上层是谁。当一个人的上层就是自己的时候,那这个人就是门派老大。

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

定义以下的join函数,用于将两个元素归为一类。 

void join(int x,int y){
    int fx=find(x), fy=find(y);    //喜门1羊的老大是喜羊羊   沸门1号的老大是沸羊羊
    if(fx != fy)                // 如果他们的老大不同
        p[fx]=fy;            //把喜门1号的老大的老大改为沸羊羊 也就是喜羊羊的老大改为沸羊羊
}

 现在我们来解答题目。

class Solution {
    public int [] p = new int[201];
    public int find(int x){
       while(p[x] != x){
       x = p[x];
        }
    return x;
    }
    public void join(int x,int y){
        int px = find(x);
        int py = find(y);
        if(px != py){
            p[px] = py;
        }
    }
    public int findCircleNum(int[][] isConnected) {
        int m = isConnected.length;
        int n = isConnected[0].length;
        for(int i = 0;i<p.length;i++){
            p[i] = i;
        }
        for(int i = 0;i<m;i++){
            for(int j = 0;j<n;j++){
                if(isConnected[i][j] == 1 && i != j){
                    join(i,j);
                }
            }
        }
        HashSet<Integer> set = new HashSet<>();
        for(int i = 0;i<m;i++){
            set.add(find(p[i]));
        }
        return set.size();
    }
}

上边用到了HashSet结构,HashSet结构不允许有重复值,对于我们的p数组,我们去查找每一个人的门主是谁然后把门主添加到set中,最后进行一个去重,剩下来的就是门主的个数,他们无法合并到一起。对于题目来说就是省份的个数。题目中只有connected为1的两个城市,我们进行join操作。

 

a9b099741c154a1abd45c9edefef79c4.png

可见效率有多低。 

三、优化find方法

我们之前的找老大的方法是层层向上,但是想一想,一个门派的所有老大只有一个人,如果我们把每个人的上层都改为门主的话,是不是就十分的方便了呢?

int find(int x){
    //如果x的上层不是门主,那么就接着查找这个人上层的老大
    if(p[x] != x) p[x] = find(p[x]); //查找老大的时候顺便将这个人的上层的老大修改为门主
    return p[x];
}

 再来看看结果。

f496c34bad914ae59840d17d40239de4.png

 代码。

class Solution {
    public int [] p = new int[201];
    public int find(int x){
       if(p[x] != x) p[x] = find(p[x]); //查找老大的时候顺便将这个人的上层的老大全部修改为门主
        return p[x];
    }
    public void join(int x,int y){
        int px = find(x);
        int py = find(y);
        if(px != py){
            p[px] = py;
        }
    }
    public int findCircleNum(int[][] isConnected) {
        int m = isConnected.length;
        int n = isConnected[0].length;
        for(int i = 0;i<p.length;i++){
            p[i] = i;
        }
        for(int i = 0;i<m;i++){
            for(int j = 0;j<n;j++){
                if(isConnected[i][j] == 1 && i != j){
                    join(i,j);
                }
            }
        }
        HashSet<Integer> set = new HashSet<>();
        for(int i = 0;i<m;i++){
            set.add(find(p[i]));
        }
        return set.size();
    }
}

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1553573.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32看似无法唤醒的一种异常现象分析

1. 引言 STM32 G0 系列产品具有丰富的外设和强大的处理性能以及良好的低功耗特性&#xff0c;被广泛用于各类工业产品中&#xff0c;包括一些需要低功耗需求的应用。 2. 问题描述 用户使用 STM32G0B1 作为汽车多媒体音响控制器的控制芯片&#xff0c;用来作为收音机频道存贮…

【有芯职说】数字芯片BES工程师

一、 数字芯片BES工程师简介 今天来聊聊数字芯片BES工程师&#xff0c;其中BES是Back End Support的缩写&#xff0c;就是后端支持的意思。其实这个岗位是数字IC前端设计和数字IC后端设计之间的一座桥&#xff0c;完成从寄存器传输级设计到具体工艺的mapping和实现。这个岗位在…

[flume$1]记录一个启动flume配置的错误

先总结&#xff1a;Flume配置文件后面&#xff0c;不能跟注释 报错代码&#xff1a; [ERROR - org.apache.flume.SinkRunner$PollingRunner.run(SinkRunner.java:158)] Unable to deliver event. Exception follows. org.apache.flume.EventDeliveryException: Failed to open…

如何在 Mac Pro 上恢复丢失的数据?

无论您多么努力&#xff0c;几乎不可能永远不会无意中删除 Mac 上的文件。当您得知删除后清空了垃圾箱时&#xff0c;您的处境可能看起来很黯淡。不要灰心。我们将教您如何使用本机操作系统功能或数据恢复工具恢复丢失的数据。奇客数据恢复Mac版可帮助恢复已从 Mac Pro 计算机上…

《Vision mamba》论文笔记

原文出处&#xff1a; [2401.09417] Vision Mamba: Efficient Visual Representation Learning with Bidirectional State Space Model (arxiv.org) 原文笔记&#xff1a; What&#xff1a; Vision Mamba: Efficient Visual Representation Learning with Bidirectional St…

YOLOv9 实现多目标跟踪

YOLOv9项目结合了YOLOv9的快速目标检测能力和DeepSORT的稳定跟踪能力&#xff0c;实现了对视频流中多个对象的实时、准确检测和跟踪。在具体应用中&#xff0c;该项目能够对视频中的行人、车辆或其他物体进行实时定位、识别和持续跟踪&#xff0c;即使在复杂环境、对象互相遮挡…

SlerfTools:简化操作,激发Solana生态创新潜能

在区块链世界的快速演变中,Solana生态系统以其独特的高性能吸引了全球的目光。然而,随着生态系统的蓬勃发展,用户和开发者面临的挑战也日渐增多。正是在这样的背景下,一个名为SlerfTools的新星项目应运而生,它承诺将为Solana带来一场革命性的变革。 项目的诞生 SlerfTools并非…

原创度检测工具分享,文章质量检测方便又简单

文章检测有利于我们了解文章内容的质量高低&#xff0c;而在以往我们检测文章只能依靠手动去检测&#xff0c;这是相当消耗工作时间的&#xff0c;但是在原创度检测工具出来之后&#xff0c;很多人开始检测文章质量就改用原创度检测工具了&#xff0c;因为使用原创度检测工具是…

YOLOv5-小知识记录(四)

0. 写在前面 本篇介绍SPP模块、FPN模块模块&#xff0c;主要也是对YOLOv5的内容的补充&#xff1a; Yolo系列算法-理论部分-YOLOv4-CSDN博客 Yolo系列算法-理论部分-YOLOv5-CSDN博客 上一篇&#xff1a; YOLOv5-小知识记录(三)-CSDN博客 1. PANet&#xff08;Path A…

49 el-input 的 模型 视图 双向同步

前言 这里来看一下 el-input 这边的 数据 和 视图的双向绑定 最开始 我以为 这部分的处理应该是 vue 这边实现的, 但是跟踪调试了一下 发现这部分的处理是业务这边 自己实现的 这部分 还是有一些 值得记录的东西, 从这里 要去理解的而是 vue 这边从宏观的框架上面来说 帮我们…

mac系统使用经验

mac安装brew brew是macos下的一个包管理工具&#xff0c;类似与centos的yum&#xff0c;ubuntu的apt-get等。 自动脚本(全部国内地址)&#xff08;在Mac os终端中复制粘贴回车下面这句话) /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/H…

基于CNN-RNN的动态手势识别系统实现与解析

一、环境配置 为了成功实现基于CNN-RNN的动态手势识别系统&#xff0c;你需要确保你的开发环境已经安装了以下必要的库和工具&#xff1a; Python&#xff1a;推荐使用Python 3.x版本&#xff0c;作为主要的编程语言。TensorFlow&#xff1a;深度学习框架&#xff0c;用于构建…

开放平台 - 互动玩法演进之路

本期作者 1. 背景 随着直播业务和用户规模日益壮大&#xff0c;如何丰富直播间内容、增强直播间内用户互动效果&#xff0c;提升营收数据变得更加关键。为此&#xff0c;直播互动玩法应运而生。通过弹幕、礼物、点赞、大航海等方式&#xff0c;用户可以参与主播的直播内容。B站…

书生·浦语大模型实战营(第二期):书生·浦语大模型全链路开源体系

非常开心能够参加到第二期的书生浦语大模型实战营&#xff0c;经过第一期的学习&#xff0c;初步了解了如何使用xtuner对模型进行微调&#xff0c;以及如何部署。遗憾的是没有更加深入学习并实现一个项目&#xff0c;此次学习过程中希望可以更进一步。 大模型称为发展通用人工…

安卓国内ip代理app,畅游网络

随着移动互联网的普及和快速发展&#xff0c;安卓手机已经成为我们日常生活和工作中不可或缺的一部分。然而&#xff0c;由于地理位置、网络限制或其他因素&#xff0c;我们有时需要改变或隐藏自己的IP地址。这时&#xff0c;安卓国内IP代理App便成为了一个重要的工具。虎观代理…

C++——C++11线程库

目录 一&#xff0c;线程库简介 二&#xff0c;线程库简单使用 2.1 传函数指针 ​编辑 2.2 传lamdba表达式 2.3 简单综合运用 2.4 线程函数参数 三&#xff0c;线程安全问题 3.1 为什么会有这个问题&#xff1f; 3.2 锁 3.2.1 互斥锁 3.2.2 递归锁 3.3 原子操作 3…

Java代码混淆技术的进阶应用与优化策略探讨

摘要 本文探讨了代码混淆在保护Java代码安全性和知识产权方面的重要意义。通过混淆技术&#xff0c;可以有效防止代码被反编译、逆向工程或恶意篡改&#xff0c;提高代码的安全性。常见的Java代码混淆工具如IPAGuard、Allatori、DashO、Zelix KlassMaster和yGuard等&#xff0…

ERROR: No matching distribution found for tb-nightly

问题描述 安装tb-lightly失败&#xff1a;ERROR: No matching distribution found for tb-nightly 解决方案 因为我的镜像源默认是清华的&#xff0c;但是pip源中没有对应的“tb-nightly”依赖包。 如果不知道的&#xff0c;也可以查看一下pip的配置&#xff1a; python -m …

12.Java语言的发展

JAVA语言的诞生是具有一定戏剧性的&#xff0c;可以说是命运多舛&#xff0c;差点凉凉&#xff0c;差点GG&#xff0c;差点嗝屁。 在1990年的时候Sun&#xff08;Stanford University Network&#xff1a;斯坦福大学网络&#xff09;公司成立了一个由 James Gosling 领导的Gree…

2024软件设计师备考讲义——(3)

程序设计语言 一、程序语言基础 1.基本概念 低级语言&#xff1a;机器语言、汇编语言高级语言&#xff1a; Fortran 科学计算&#xff0c;执行效率高Pascal 为教学开发&#xff0c;表达能力强Prolog 逻辑性程序设计语言C语言 指针操作能力强&#xff0c;可以开发系统级软件&a…