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

这篇具有很好参考价值的文章主要介绍了【LeetCode】LeetCode 547. 省份数量(Java版 什么是并查集)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【LeetCode】LeetCode 547. 省份数量(Java版 什么是并查集),leetcode,算法,职场和发展

  📝个人主页:哈__

期待您的关注 

【LeetCode】LeetCode 547. 省份数量(Java版 什么是并查集),leetcode,算法,职场和发展

一、题目描述

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

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

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

返回矩阵中 省份 的数量。

【LeetCode】LeetCode 547. 省份数量(Java版 什么是并查集),leetcode,算法,职场和发展

【LeetCode】LeetCode 547. 省份数量(Java版 什么是并查集),leetcode,算法,职场和发展

二、思路讲解 

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

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

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

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

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

【LeetCode】LeetCode 547. 省份数量(Java版 什么是并查集),leetcode,算法,职场和发展

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

【LeetCode】LeetCode 547. 省份数量(Java版 什么是并查集),leetcode,算法,职场和发展

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

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

定义以下的find函数。p是一个数组,用于记录每一只羊的上层是谁。当一只羊的上层就是自己的时候,那这只羊就是门派老大。find函数用一句话来解释,就是查找一只羊的老大是谁。

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操作。

【LeetCode】LeetCode 547. 省份数量(Java版 什么是并查集),leetcode,算法,职场和发展

可见效率有多低。 

三、优化find方法

我们之前的找老大的方法是层层向上,但是想一想,一个门派的所有老大只有一只羊,如果我们把每只羊的上层都直接改为门主的话,这样不需要在层层的往上找,是不是就十分的方便了呢?(喜羊羊和沸羊羊都是无限体力的工作机器)

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

 再来看看结果。

【LeetCode】LeetCode 547. 省份数量(Java版 什么是并查集),leetcode,算法,职场和发展

 代码。文章来源地址https://www.toymoban.com/news/detail-854630.html

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();
    }
}

到了这里,关于【LeetCode】LeetCode 547. 省份数量(Java版 什么是并查集)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 图论02-并查集的实现(Java)

    2.并查集理论基础 并查集的作用 并查集的实现 Java代码实现 路径压缩 优化后完整代码

    2024年03月25日
    浏览(45)
  • Java高阶数据结构 & 并查集 & 最小生成树

    并查集与最小生成树 1.1 并查集的原理 在一些应用问题中,我们常常会遇到一类问题 一开始是一个人 后来新增的人可能与这个人有关系,也可能与这个人无关系。 一个人与一个人有关系,这个人与另一个人也有关系,那么三人都有关系。 有关系的和没关系的之间是不同的类

    2024年02月03日
    浏览(40)
  • 并查集(种类并查集,带权并查集)

    链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网   动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形。A吃B,B吃C,C吃A。 现有N个动物,以1-N编号。每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种。 有人用两种说法对这N个动物所

    2024年02月11日
    浏览(38)
  • 【蓝桥模板】——如何用7行代码,优雅地拿捏并查集?(并查集模板)

    全文目录🧭 👩‍👩‍👦并查集-亲戚问题 🚀传送锚点​  💡思路点拨 🍞代码详解   👶🏻并查集-蓝桥幼儿园 🚀传送锚点  💡思路点拨 🍞代码详解   🌼并查集-合根植物 🚀传送锚点  💡思路点拨 🍞代码详解    🏰并查集-城邦 🚀传送锚点​​​​​​​  💡思

    2023年04月09日
    浏览(32)
  • 【模板】并查集

    并查集是解决两元素是否属于同一集合,将一个集合合并另一集合的数据结构。具体来说,我们使用数字代替集合,比如集合1,集合2.使用数组f[i]维护元素i属于的集合,比如f[2] = 4表示元素2属于集合4。具体我们有以下实现功能的代码 1 初始化表示集合的数组。     表示元素

    2024年01月25日
    浏览(34)
  • 并查集

    并查集 并查集是用来判断两个元素是否属于同一个集合 即判断他们的根节点是否相同 1. 初始化 2.查询根节点 3.合并 集合变为一个长长的链时,查找变得十分麻烦,此时我们需要路径压缩 即每个人的直接根节点就是最上面的根节点 我们判断两个元素是否是同一个集合,看的

    2024年02月08日
    浏览(30)
  • 【数据结构】--并查集

    目录 一、概念 ​编辑 二、应用场景--“连接”问题(属于同一Qu 三、实现思路  四、如何存储数据 五、定义接口 1.初始化(init) 2.其他 isSame() 六、抽象类 六、Quick Find【v1 所在集合的所有元素都指向 v2 的根节点】 1.Union 1.Union图解 2.注意点:  3.代码实现 2.find  1.find图

    2023年04月09日
    浏览(33)
  • 【数据结构】并查集

    并查集是简单的数据结构,学会并查集,为图打好基础。 是树状的数据结构,用于处理相交集合的合并与查询 通常用森林表示,一片森林表示一个集合 并查集一般需要完成 查找元素属于哪个集合 查看两个元素是否属于同一个集合 将两个集合归并成一个集合 集合的个数 假

    2024年02月19日
    浏览(36)
  • 【高阶数据结构】——并查集

    在一些应用问题中, 需要将n个不同的元素划分成一些不相交的集合。开始时,每个元素自成一个单元素集合, 然后按一定的规律将归于同一组元素的集合合并 。在此过程中要 反复用到查询某一个元素归属于那个集合的运算 。适合于描述这类问题的抽象数据类型称为 并查集

    2024年02月16日
    浏览(37)
  • C++:合并集合(并查集)

    一共有n个数,编号是1~n,最开始每个数各自在一个集合中。 现在要进行m个操作,操作共有2种: 1.“M a b”,将编号为a和b的两个数的所在的集合合并,如果两个数已经在同一个集合中则忽略这个操作 2.“Q a b”,询问编号为a和b的两个数是否在同一个集合中 第一行输入整数

    2024年02月13日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包