并查集python实现及题目练习

文章目录

  • 1. 并查集概念
    • 1.1 理解并查集:简介与应用场景
    • 1.2 Python 实现并查集及优化策略
    • 1.3 扁平化栈实现
    • 1.4 分析并查集的时间复杂度
  • 2. 情侣牵手
  • 3. 相似字符串
  • 4. 岛屿数量

如果想了解并查集基础推荐去看左程云大神的算法讲解,非常不错,b站和油管上都有它的视频

1. 并查集概念

1.1 理解并查集:简介与应用场景

概述:
并查集(Disjoint Set)是一种用于处理集合合并和查询等问题的数据结构。

并查集的作用:

  • 解决元素分组与连接问题
  • 用于图论中的最小生成树算法、连通性问题、网络分区等

1.2 Python 实现并查集及优化策略

class UnionFind:def __init__(self, n):# 初始化时,每个元素的父节点为自己self.parent = list(range(n))# 初始化时每个树的深度为0(也可以设置为1)self.rank = [0] * n# 查找操作(扁平化)def find(self, x):if self.parent[x] != x:  # 如果当前节点的父节点不是自己,说明不是根节点# 路径压缩,将当前节点直接连接到根节点self.parent[x] = self.find(self.parent[x])return self.parent[x]  # 返回根节点的索引# 合并操作(小挂大)def union(self, x, y):root_x = self.find(x)  # 找到元素 x 的根节点root_y = self.find(y)  # 找到元素 y 的根节点if root_x != root_y:  # 如果两个元素不在同一个集合中if self.rank[root_x] < self.rank[root_y]:  # 如果树的深度(秩)小于另一个树# 将较浅的树的根节点连接到较深的树的根节点self.parent[root_x] = root_yelif self.rank[root_x] > self.rank[root_y]:self.parent[root_y] = root_xelse:  # 如果两个树深度相同,则任意连接一个到另一个,并将深度加一self.parent[root_y] = root_xself.rank[root_x] += 1

优化策略:

  • 路径压缩优化(扁平化):在查找操作中,将节点直接连接到根节点,降低树的深度
  • 按秩合并优化(小集合挂大集合):将深度较浅的树挂在深度较深的树下,保持树的平衡

1.3 扁平化栈实现

def find(self, x):# 使用栈记录路径path = []# 找到根节点while self.parent[x] != x:path.append(x)x = self.parent[x]# 路径压缩:将路径上的所有节点直接连接到根节点for node in path:self.parent[node] = xreturn x

1.4 分析并查集的时间复杂度

时间复杂度分析:

  • 查找操作(Find):近似为 O(1)。
  • 合并操作(Union):近似为 O(1)。
  • 综合时间复杂度:近似为 O(α(n)),其中 α(n) 是 Ackermann 函数的反函数,通常视为常数级别。

2. 情侣牵手

测试链接:https://leetcode.cn/problems/couples-holding-hands/

image-20240406161605370

image-20240406161613003

  1. 分析
分析:将每对情侣的对数看成一个集合,例如:第一对情侣(0,1),属于集合{0};第二对情侣(2,3),属于集合{1}...所以最开始一定有n个集合思路:就是每次遍历相邻的两个人,如果它们不是一对,那么它们就分别属于各自的那一对,将这两对的集合合并,此时总集合数就少1求解答案(两种):1. 对于每一个集合,如果里面有m对情侣,那么就需要交换m-1次2. 总的集合数减去合并后的集合数例子,[0,4,2,1,3,5]:- 一共3对情侣,3个集合,{0},{1},{2}- 遍历0和4,0//2 != 4//2,它们不是一对,将它们的集合合并,此时有2个集合:{0,2},{1}- 遍历2和1,2//2 != 1//2,它们不是一对,将它们的集合合并,此时有1个集合:{0,2,1}- 所以一共需要交换:1. 只有1个集合,这个集合有3对情侣,需要交换3-1=2次2. 原来有3个集合,现在只有1个集合,需要交换3-1=2次
  1. 代码
class UnionFind:def __init__(self, n):self.father = [0] * n# 初始化集合for i in range(n):self.father[i] = i# 记录集合的数量self.sets = ndef find(self, x):if self.father[x] != x:self.father[x] = self.find(self.father[x])return self.father[x]def union(self, x, y):fx = self.find(x)fy = self.find(y)# 如果它们的father不相同,说明不是一对情侣,需要合并if fx != fy:self.father[fx] = fy# 合并后集合数-1self.sets -= 1class Solution(object):def minSwapsCouples(self, row):""":type row: List[int]:rtype: int"""n = len(row)couple = UnionFind(n // 2)for i in range(0, n - 1, 2):# 依次遍历两个人,是一对情侣就不合并,不是一对情侣就合并couple.union(row[i] // 2, row[i + 1] // 2)return n // 2 - couple.sets

image-20240406165156737

3. 相似字符串

测试链接:https://leetcode.cn/problems/H6lPxb/

image-20240406201614718

image-20240406201623530

  1. 题目分析
1. 什么是字母异位词?假如给一个字符串abc,它的字母异位词有acb,bac,bca,cab,cba。当然,abc也同样是它们的字母异位词2. 什么是相似?给定两个字符串x,y(都由小写字母组成),分两种情况:- 如果x和y不做任何操作就相同,那它们相似- 如果x和y不同,交换x中任意两个字母的位置能变成y,就说明x和y相似3. 什么是相似字符串组?根据示例1,strs=['tars','rats','arts','star']- 首先它们四个各自为一组,共四个组- strs[0]和strs[1]相似,把它们分到一组- strs[0]和strs[2]不相似,不把strs[2]加入到strs[0]那一组- strs[0]和strs[3]不相似,不把strs[3]加入到strs[0]那一组- strs[1]和strs[2]相似,把strs[2]加入到strs[1]那一组- strs[1]和strs[3]不相似,不把strs[3]加入到strs[1]那一组- ...- strs[3]和前面的字符串都不相似,自己单独为一组- 最后就分为了两个组,{strs[0],strs[1],strs[2]},{strs[3]}- 很明显地就是用并查集去分组- 只要剩余的字符串与一个组内的任一字符串相似就将它们合并
  1. 代码
class UnionFind:def __init__(self, n):self.father = [0] * nself.size = [1] * nfor i in range(n):self.father[i] = iself.sets = ndef find(self, x):if self.father[x] != x:self.father[x] = self.find(self.father[x])return self.father[x]# 小挂大def union(self, x, y):fx = self.find(x)fy = self.find(y)if fx != fy:if self.size[fx] >= self.size[fy]:self.father[fy] = fxself.size[fx] += self.size[fy]else:self.father[fx] = fyself.size[fy] += self.size[fx]self.sets -= 1class Solution(object):def numSimilarGroups(self, strs):""":type strs: List[str]:rtype: int"""# 共有n个字符串n = len(strs)# 每个字符串长度为mm = len(strs[0])connect = UnionFind(n)for i in range(n):for j in range(i + 1, n):# 两两比较字符串,如果它们不在同一个组中,并且它们相似,就合并if (connect.find(i) != connect.find(j)):diff = 0# 依次比较strs[i]和strs[j],因为strs中的字符串都互为字母异位词# 所以只需要看strs[i]和strs[j]有几个字符不一样就行了for k in range(m):if strs[i][k] != strs[j][k]:diff += 1# strs[i]要么完全和strs[j]一样,要么有两个字符不同,这样才满足相似的条件if diff >= 3:break# 如果相似,就合并if diff == 0 or diff == 2:connect.union(i, j)return connect.sets

image-20240406203301364

4. 岛屿数量

测试链接:https://leetcode.cn/problems/number-of-islands/

image-20240406211948653

image-20240406211958246

  1. 分析
思路:使用并查集的话就是先将每个1都视为1个集合,如果它的上下左右也是1,就合并两个集合下标转换:将二维下标转换为一维下标,例如下面是一个4×4的二维表,坐标[i][j]转换为一维的就是i*m + j(m为列的数量)n\m 0 1 2 30  0 1 2 31  4 5 6 72  8 9 10 113  12 13 14 15
  1. 代码
class UnionFind:def __init__(self, n, m, grid):# 正常建立并查集,我们只需要关注“1”就行了,“0”不用管self.father = [-1] * ((n - 1) * m + m)self.sets = 0for i in range(n):for j in range(m):if grid[i][j] == '1':self.father[i * m + j] = i * m + jself.sets += 1def find(self, x):if self.father[x] != x:self.father[x] = self.find(self.father[x])return self.father[x]def union(self, x, y):fx = self.find(x)fy = self.find(y)if fx != fy:self.father[fy] = fxself.sets -= 1class Solution(object):def numIslands(self, grid):""":type grid: List[List[str]]:rtype: int"""n = len(grid)m = len(grid[0])area = UnionFind(n, m, grid)for i in range(n):for j in range(m):if grid[i][j] == '1':# “0”不用管的原因是因为我们合并x,y的时候,x,y对应的二维坐标在二维表中一定是“1”# 下面只需检查每个“1”的左上是否为1,就不用上下左右全部检查了if j > 0 and grid[i][j - 1] == '1':area.union(i * m + j, i * m + j - 1)if i > 0 and grid[i - 1][j] == '1':area.union(i * m + j, (i - 1) * m + j)return area.sets

image-20240406212823666

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

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

相关文章

python 02字符串

字符串可能是用到最多的数据类型了&#xff0c;所有标准序列操作&#xff08;索引、切片、乘法、成员资格检查、长度、最小值和最大值&#xff09;都适用于字符串 但别忘了字符串是不可变的&#xff0c;因此所有的元素赋值和切片赋值都是非法的。 1.居中效果 默认为空格 可…

在不同操作系统中搭建Python编程环境

1 在不同操作系统中搭建Python编程环境 1.1 在Linux系统中搭建Python编程环境 1. 检查Python版本 在你的系统中运行应用程序Terminal&#xff08;如果你使用的是Ubuntu&#xff0c;可按Ctrl Alt T&#xff09;&#xff0c;打开一个终端窗口。为确定是否安装了Python&…

为何网易游戏会选择引入OceanBase数据库

本文作者&#xff1a;田维繁&#xff0c;网易游戏关系型数据库小组负责人 作为中国游戏开发领域的佼佼者&#xff0c;网易游戏始终站在网络游戏自主研发的前沿。其产品及周边产品线丰富多样&#xff0c;因此&#xff0c;为满足各种业务场景的需求&#xff0c;需要多种不同的数据…

【环境变量】常见的环境变量 | 相关指令 | 环境变量系统程序的结合理解

目录 常见的环境变量 HOME PWD SHELL HISTSIZE 环境变量相关的指令 echo&env export unset 本地变量 环境变量整体理解 程序现象_代码查看环境变量 整体理解 环境变量表 环境变量表的传递 环境变量表的查看 测试验证 少说废话&#x1f197; 每个用户…

48V转15V,48V转12V,48V转24V高效率降压恒压芯片SL3041电路简单

在现代电子设备中&#xff0c;电源转换是一个关键且常见的技术。特别是对于那些需要将48V电压转换为更低电压&#xff08;如15V、12V或24V&#xff09;的设备&#xff0c;一个高效、可靠的降压恒压芯片至关重要。本文将详细介绍一款名为SL3041的高效率降压恒压芯片&#xff0c;…

#{} 和 ${}区别

1、参数是Integer类型时候没区别&#xff08;#是预编译SQL&#xff0c;$是即时SQL&#xff09; 2、当参数是String类型时&#xff0c;就会出错了 &#xff08;1&#xff09;这是$的报错信息&#xff0c;因为我们的参数admin并没有加引号所以不满足字符串条件 (2)正确的SQL &am…

蓝牙学习十(扫描)

一、简介 从之前的文章中我们知道&#xff0c;蓝牙GAP层定义了四种角色&#xff0c;广播者&#xff08;Broadcaster&#xff09;、观察者&#xff08;Observer&#xff09;、外围设备&#xff08;Peripheral&#xff09;、中央设备&#xff08;Central&#xff09;。 之前的学习…

基础总结篇:Activity生命周期

private int param 1; //Activity创建时被调用 Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.i(TAG, “onCreate called.”); setContentView(R.layout.lifecycle); Button btn (Button) findViewById(R.id.…

Python实现 AI 绘图(非常详细)零基础入门到精通,收藏这一篇就够了

今天给大家带来了 Python 对接阿里大模型&#xff0c;通过 AI 实现文本生成图片。 相关资料 这个功能使用的主要 API 是阿里的大模型服务。 开通服务 阿里文档 https://help.aliyun.com/zh/dashscope/developer-reference/quick-start-1?disableWebsiteRedirecttrue 获取 a…

K8S之Job和CronJob控制器

这里写目录标题 Job概念适用场景使用案例 CronJob概念适用场景使用案例 Job 概念 Job控制器用于管理Pod对象运行一次性任务&#xff0c;例如&#xff1a;对数据库备份&#xff0c;可以直接在k8s上启动一个mysqldump备份程序&#xff0c;也可以启动一个pod&#xff0c;这个pod…

Day3-HBase重要概念

HBase 结构 HRegion 概述 在HBase中&#xff0c;会从行键方向上对表来进行切分&#xff0c;切分出来的每一个结构称之为是一个HRegion 切分之后&#xff0c;每一个HRegion会交给某一个HRegionServer来进行管理。HRegionServer是HBase的从节点&#xff0c;每一个HRegionServ…

C++ 内存分配时地址对齐

如果数据地址的对齐与CPU相兼容&#xff0c;那么CPU读写内存时性能会更高。 因此在C中&#xff0c;有时会希望在堆或栈中分配内存时&#xff0c;返回的地址能按照特定的长度对齐。 如果希望在栈中分配的内存时&#xff0c;返回地址按照特定长度对齐&#xff0c;可以使用 alig…

光伏接口转接器配合光伏规约转换器实现发电用电信息采集支持接入各个型号逆变器

1.产品概述 DAQ-GP-485PIA光伏接口转接器&#xff08;以下简称转接器&#xff09;是我公司针对光伏发电领域国家电网公司最新需求设计的&#xff0c;光伏接口转接器是配合光伏规约转换器&#xff0c;实现逆变器发电、用电信息采集的设备。支持锦浪、古瑞瓦特、固德威、华为、奥…

提升团队工程交付能力,从“看见”工程活动和研发模式开始

作者&#xff1a;张裕、雅纯 理想中的研发团队应当具有以下特征&#xff1a; 总是工作在最高优先级的事项上 理想的研发团队能够识别并始终集中精力在当前最紧迫和最有价值的任务上。这需要团队具备出色的项目管理能力和决策能力&#xff0c;以便能够正确评估优先级&#xff0…

Vue 项目如何在VSCode中进行断点调试

概要&#xff1a; 简单介绍一下&#xff0c;在VSCode中如何对Vue项目进行断点调试。具体内容包括但不限于&#xff1a;如何配置调试环境、如何在代码中设置断点、如何启动调试以及如何解决在调试过程中可能遇到的问题。 实际开发中&#xff0c;我们的前端项目一般都是在浏览器…

算法 day28 回溯4

93 复原IP地址 给定一个只包含数字的字符串 s &#xff0c;用以表示一个 IP 地址&#xff0c;返回所有可能的有效 IP 地址&#xff0c;这些地址可以通过在 s 中插入 ‘.’ 来形成。你 不能 重新排序或删除 s 中的任何数字。你可以按 任何 顺序返回答案。 有效 IP 地址 正好由…

windows 系统下 mysql 数据库的下载与安装(包括升级安装)

windows 系统下 mysql 数据库的下载与安装&#xff08;包括升级安装&#xff09; 一、mysql 介绍&#xff1a; MySQL 是一个关系型数据库管理系统&#xff0c;由瑞典 MySQL AB 公司开发&#xff0c;属于 Oracle 旗下产品。 MySQL 是最流行的关系型数据库管理系统之一&#xf…

从300亿分子中筛出6款,结构新且易合成,斯坦福抗生素设计AI模型登Nature子刊

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 新建了免费的人工智能中文站https://ai.weoknow.com 新建了收费的人工智能中文站https://ai.hzytsoft.cn/ 更多资源欢迎关注 全球每年有近 500 万人死于抗生素耐药性&#xff0c;因此迫切需要新的方法来对抗耐药菌株。 …

llama2的python视角

1 调试代码 if __name__ __main__ :config ModelArgs(dim8, n_layers2, n_heads32, n_kv_heads32, vocab_size32000, hidden_dimNone, multiple_of256, norm_eps1e-05, max_seq_len3, dropout0.0)model Transformer(config)input_tokens torch.randint(0, 32000, (1, 3)) …

【已解决】HalconDotNet.HOperatorException:“HALCON error #1201: Wrong type of control

前言 最近在学习Halcon视觉和C#的联合开发&#xff0c;碰到一个比较有意思的问题记录一下&#xff0c;大致的报错信息是说我用的halcondotnet版本和我在halcon导出的使用的halcondotnet.dll版本不一致&#xff0c;所以才报错的&#xff01; 解决 首先你得找到你安装halcon的…