并并并并·病查坤

news2025/2/26 18:40:00

P1、什么是并查集

引用自百度百科:

并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。

并查集是一种树型的数据结构,用于处理一些不相交集合(disjoint sets)的合并及查询问题。常常在使用中以森林来表示。

简单来说,并查集是一种以树形结构来表示不同种类数据的集合。一般当我们需要用到数据的连通性时会用到它。

并查集维护一个数组parent,parent数组中维护的不是元素本身,而是元素的下标索引,当然,这个下标索引是指向该元素的父元素的。

image-20240425223445850

引用自:【算法与数据结构】—— 并查集-CSDN博客

P2、简单、无优化的并查集

// 未改进版本
public class Djset {
    private int[] parent;  // 记录节点的根
    public Djset(int n) {
        for (int i = 0; i < n; i++) 
            parent[i] = i;
    }

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

    public void merge(int x, int y) {
        int rootx = find(x);
        int rooty = find(y);
        if (rootX != rootY) {
            parent[rootY] = rootX;
        }
    }
}

这种没有任何优化的并查集,比较简单,但是效率很低。为什么?

问题1:

当合并两个节点时,这里是没有任何判断的,便直接将rootx设置成了rooty的父节点。

假如rooty的叶子节点深度比rootx的叶子节点深度大呢?此时,树的深度会持续增加,会造成后续的节点查询时间长。

问题2:

在寻找某个节点的根节点的过程中,我们也未对其父节点和祖父节点…等作任何操作。

假如该节点会被合并(merge)很多次,而每次都要经过父节点、祖父节点…层层寻找,造成了不必要的时间浪费。

比如:

image-20240425221005247

这样,树的深度便在无形之中增加了1。

如果反过来,将rootx的父节点设置为rooty,看下效果:

image-20240425220909242

树的深度是没有增加的,不会对后续节点造成影响。

P3、优化后的并查集【按秩合并】【路径压缩】

// 注意:使用该代码,并不能使得所有的元素都直接指向根节点,仍然存在间接的指向
public class Djset {
    private int[] parent;  // 记录节点的根
    private int[] rank;  // 记录根节点的深度,优化合并操作

    // 构造函数,初始化每个节点的根为其自身,并设置初始秩为0
	public Djset(int n) {
    	parent = new int[n];
   		rank = new int[n];
  	  	for (int i = 0; i < n; i++) {
  	      	parent[i] = i;
        	rank[i] = 1; // 确保初始化每个节点的初始秩也为1
   		}
	}

    // 查找x的根节点,同时进行路径压缩
    public int find(int x) {
        if (x != parent[x]) {
            parent[x] = find(parent[x]);  // 路径压缩至根节点
        }
        return parent[x];
    }

    // 合并x和y所在的集合,按秩合并优化
    public void merge(int x, int y) {
        int rootX = find(x);
        int rootY = find(y);
        if (rootX != rootY) {
            // 按秩合并:将秩较小的集合合并到较大的集合
            if (rank[rootX] < rank[rootY]) {
                int temp = rootX;
                rootX = rootY;
                rootY = temp;
            }
            parent[rootY] = rootX;  // 根据秩决定合并方向
            if (rank[rootX] == rank[rootY]) {
                rank[rootX]++;
            }
        }
    }
}

这里主要针对未改进的版本,做了两点优化 【按秩合并】和【路径压缩】

① 按秩合并

好的,让我们先弄清楚什么是按秩合并

秩:我们暂时将其定义为节点的最大深度(从节点自身开始,到叶子节点的最大深度)

按秩合并:主要是针对merge函数,在合并两个集合时,将秩大的根节点设置为秩小的根节点的父节点。意思是当要合并两个根节点A、B时,如果节点A的秩大于节点B的秩,那么将节点A设置为节点B的父节点,反之亦然。

比如:

image-20240425220909242

通过将秩大的根节点设置为合并后的根节点,避免了树的深度增加。

② 路径压缩

同样,先弄清楚什么是路径压缩

路径压缩:主要针对find函数,当在寻找一个节点A的根节点root时,直接将节点A的父节点B、祖父节点C…等节点全部指向根节点root。

优点:这样在下次寻找A的根节点、B的根节点、C的根节点时可以节省很长一段搜索路径。

如:

image-20240425221904252

接下来,来几个简单的困难题:

原题链接:

839. 相似字符串组 - 力扣(LeetCode)

image-20240426215746045

这个题目首先要理解相似的定义:

两个字符串相似的含义是能够通过交换两个字符的位置,得到另外一个字符串。

根据题目来看,给的字符串中的字母是相同的,不同的顺序,那么相似只有两种情况:两个字符串的对应位置中只有 0 个或者 2 个不同。

我们将字符串看作节点,两重 for 循环,实现对节点之间两两组合,判断两个节点是否相似,判断相似的方法是:

两个字符串的对应位置中只有 0 个或者 2 个不同;

如果两个字符串相似则将他们归入一组,之后遍历时,如果不是同一组就需要进行判断。

初始化并查集数组,并初始化集合数,每次合并减一。

class Solution {
    public static int[] father = new int[10000];
    public static int sets;
    public static void build(int n) {
        for (int i = 0; i < n; i++) {
            father[i] = i;
        }
        sets = n;
    }
    public static int find(int i) {
        if (i != father[i]) {
            father[i] = find(father[i]);
        }
        return father[i];
    }
    public static void union(int x, int y) {
        int fx = find(x);
        int fy = find(y);
        if (fx != fy) {
            father[fx] = fy;
            sets--;
        }
    }
    public int numSimilarGroups(String[] strs) {
        int n = strs.length;
        int m = strs[0].length();
        build(n);
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                if (find(i) != find(j)) {
                    int diff = 0;
                    for (int k = 0; k < m && diff < 3; k++) {//不同之处大于三那就没有意义了,一定不相似
                      
                        if (strs[i].charAt(k) != strs[j].charAt(k)) {
                            diff++;
                        }
                    }
                    if (diff == 0 || diff == 2) {
                        union(i, j);
                    }
                }
            }
        }
        return sets;
    }
}

原题链接:

765. 情侣牵手 - 力扣(LeetCode)

image-20240425204217850

首先,我们总是以「情侣对」为单位进行设想:

当有两对情侣相互坐错了位置,ta们两对之间形成了一个环。需要进行一次交换,使得每对情侣独立(相互牵手)

长度1的自环

如果三对情侣相互坐错了位置,ta们三对之间形成了一个环,需要进行两次交换,使得每对情侣独立(相互牵手)

image.png

如果四对情侣相互坐错了位置,ta们四对之间形成了一个环,需要进行三次交换,使得每对情侣独立(相互牵手)

也就是说,如果我们有 k 对情侣形成了错误环,需要交换 k - 1 次才能让情侣牵手。

于是问题转化成 n / 2 对情侣中,有多少个这样的环。

如果他们本来就是情侣,他们处于大小为1的错误环中,只需要交换0次。

如果不是情侣,说明他们呢两对处在同一个错误环中,我们将他们合并,将所有的错坐情侣合并后,答案就是情侣对 - 环个数。

class Solution {
    public int minSwapsCouples(int[] row) {
        int n = row.length;
        bulid(n / 2);
        for (int i = 0; i < n; i += 2) {
            union(row[i] / 2, row[i + 1] / 2);

        }
        return n / 2 - set;
    }
    //首先计算数组长度的一半(即情侣对数),然后调用bulid方法初始化并查集,
    //之后遍历数组,对每一对执行union操作合并它们所在的集合。
   // 最后,返回初始集合数量减去最终集合数量的结果,即为最少需要交换的次数。

    public static int[] father = new int[100];
    public static int set;

    public static void bulid(int x) {
        set = x;
        for (int i = 0; i < x; i++) {
            father[i] = i;
        }
    }
    public static int find(int i){
        if(i==father[i])return father[i];
        else return find(father[i]);
    }

    public static void union(int x,int y){
        if(find(x)!=find(y)){
            father[find(x)]=find(y);
            set--;
        }
    }
}

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

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

相关文章

【数据标注】使用LabelImg标注YOLO格式的数据(案例演示)

文章目录 LabelImg介绍LabelImg安装LabelImg界面标注常用的快捷键标注前的一些设置案例演示检查YOLO标签中的标注信息是否正确参考文章 LabelImg介绍 LabelImg是目标检测数据标注工具&#xff0c;可以标注两种格式&#xff1a; VOC标签格式&#xff0c;标注的标签存储在xml文…

insightface 环境配置

首先创建续集环境&#xff1a; conda create -n insightface3 python3.8 然后打开此虚拟环境&#xff1a;conda activate insightface3 然后安装&#xff1a; pip install insightface 再安装&#xff1a;pip install onnxruntime-gpu 就可以了

零基础俄语培训哪家好,柯桥俄语培训

1、Мощный дух спасает расслабленное тело. 强大的精神可以拯救孱弱的肉体。 2、Единственное правило в жизни, по которому нужно жить — оставаться человеком в лю…

物联网的基本功能及五大核心技术——青创智通

工业物联网解决方案-工业IOT-青创智通 物联网基本功能 物联网的最基本功能特征是提供“无处不在的连接和在线服务”&#xff0c;其具备十大基本功能。 &#xff08;1&#xff09;在线监测&#xff1a;这是物联网最基本的功能&#xff0c;物联网业务一般以集中监测为主、控制为…

qml和c++结合使用

目录 文章简介1. 创建qml工程2. 创建一个类和qml文件&#xff0c;修改main函数3. 函数说明&#xff1a;4. qml 文件间的调用5. 界面布局6. 代码举例 文章简介 初学qml用来记录qml的学习过程&#xff0c;方便后面归纳总结整理。 1. 创建qml工程 如下图&#xff0c;我使用的是…

本地Mysql开启远程访问(图文)

目录 1. 问题所示2. 原理分析3. 解决方法 1. 问题所示 事因是访问同事的数据库时&#xff0c;出现无法访问 出现1130 - Host ‘IT07’ is not allowed to connect to this MySQL server截图如下&#xff1a; 2. 原理分析 如果账号密码地址都正常的情况下&#xff0c;这是没开…

SQLite尽如此轻量

众所周知&#xff0c;SQLite是个轻量级数据库&#xff0c;适用于中小型服务应用等&#xff0c;在我真正使用的时候才发现&#xff0c;它虽然轻量&#xff0c;但不知道它却如此轻量。 下载 官网&#xff1a; SQLite Download Page 安装 1、将下载好的两个压缩包同时解压到一个…

基于springboot的高校宣讲会管理系统

文章目录 项目介绍主要功能截图&#xff1a;部分代码展示设计总结项目获取方式 &#x1f345; 作者主页&#xff1a;超级无敌暴龙战士塔塔开 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简历模板、学习资料、面试题库【关注我&#xff0c;都给你】 &…

前端工程化Vue使用Node.js永久设置国内高速npm镜像源

前端工程化Vue使用Node.js永久设置国内高速npm镜像源 接续上篇错误收录&#xff0c;此篇通过简单配置永久设置国内高速npm镜像源方法 1.更换新版镜像 清空npm缓存 npm cache clean --force修改回原版镜像源或直接删除配置过的镜像源 npm config set registry https://registr…

pve(Proxmox VE)安装i225v网卡驱动

配置pve源 备份原来的源 mv /etc/apt/sources.list /etc/apt/sources.list.bak打开文件 vi /etc/apt/sources.list将以下内容粘贴进去 deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm main contrib non-free non-free-firmwaredeb https://mirrors.tuna.tsing…

2024景区五一游园会活动策划方案

2024景区营地五一发酵面包市集主题游园会&#xff08;面包狂想曲主题&#xff09;活动策划方案-59P 方案页码&#xff1a;59页 文件格式&#xff1a;pptx 方案简介&#xff1a; 面包派对 如约而至 你有见过面包发酵的过程吗? 看着面团从手掌大小 不断膨胀到一倍、两倍、…

CLIP论文笔记:Learning Transferable Visual Models From Natural Language Supervision

导语 会议&#xff1a;ICML 2021链接&#xff1a;https://proceedings.mlr.press/v139/radford21a/radford21a.pdf 当前的计算机视觉系统通常只能识别预先设定的对象类别&#xff0c;这限制了它们的广泛应用。为了突破这一局限&#xff0c;本文探索了一种新的学习方法&#x…

校车车载4G视频智能监控系统方案

一、项目背景 随着社会的快速发展&#xff0c;校车安全问题日益受到人们的关注。为了提高校车运营的安全性&#xff0c;保障学生的生命安全&#xff0c;我们提出了一套校车车载4G视频智能监控系统方案。该系统能够实时监控校车内部和外部环境&#xff0c;及时发现并处理潜在的…

全志ARM-网络链接

命令扫描周围的WIFI热点 nmcli dev wifi 命令接入网络 nmcli dev wifi connect &#xff08;WiFi名&#xff0c;不要有空格&#xff09;password (WiFi密码) 查看IP地址 ip addr show wlan0或ifconfig 出现successfully就连接成功了

qt5core.dll怎么下载,qt5core.dll丢失能否修复?

qt5core.dll的丢失真是让人头疼。这个Visual C Redistributable for Visual Studio 2015的运行时库被许多程序和游戏所依赖&#xff0c;一旦缺失了qt5core.dll&#xff0c;就会面临无法打开程序或游戏&#xff0c;甚至系统崩溃等一系列问题。 qt5core.dll的消失会带来以下麻烦 …

沉浸式推理乐趣:体验线上剧本杀小程序的魅力

在这个信息爆炸的时代&#xff0c;人们的娱乐方式也在不断地推陈出新。其中&#xff0c;线上剧本杀小程序以其独特的沉浸式推理乐趣&#xff0c;成为了许多人的新宠。它不仅让我们在闲暇之余享受到了推理的快乐&#xff0c;更让我们在虚拟的世界里感受到了人性的复杂与多彩。 线…

可视化大屏对浅色系果断说“不”

可视化大屏拒绝浅色系的原因有以下几点&#xff1a; 对比度不足&#xff1a;浅色系在大屏上可能会导致对比度不足&#xff0c;使得数据和图表的展示不清晰&#xff0c;影响信息的传达和理解。可读性差&#xff1a;浅色系的文字和图表在大屏上可能会显得模糊不清&#xff0c;使…

有什么因素会影响IP稳定性?

IP稳定性指的是IP地址在一段时间内保持不变的能力&#xff0c;对于网络连接的安全性和可靠性至关重要。以下是一些可能影响IP稳定性的主要因素&#xff1a; 网络服务提供商&#xff08;ISP&#xff09;的政策&#xff1a;不同的ISP对于IP地址的管理和使用有不同的政策。一些IS…

使用 NVM 动态切node版本

一、安装nvm 官网链接&#xff1a; Release 1.1.9 coreybutler/nvm-windows GitHub 无脑安装直接下一步 安装完之后验证一下&#xff1a; #打开命令行输入命令 nvm 这样就是安装好了&#xff0c;然后我们开始安装node。 二、使用nvm安装node 1、去node官网获取版本号 …

2024年Q1季度洗衣机行业线上市场销售数据分析

Q1季度洗衣机线上市场表现不如预期。 根据鲸参谋数据显示&#xff0c;2024年1月至3月线上电商平台&#xff08;京东天猫淘宝&#xff09;洗衣机累计销量约650万件&#xff0c;环比下降14%&#xff0c;同比下降14%&#xff1b;累计销售额约96亿元&#xff0c;环比下降30%&#…