一分钟说清楚并查集

简介: 思路比结论重要,有收获就是好的。

分离集合(disjoint set)是一种经典的数据结构,它有三类操作:

Make-set(a):生成包含一个元素a的集合S;

Union(X, Y):合并两个集合X和Y;

Find-set(a):查找元素a所在集合S,即通过元素找集合句柄;

它非常适合用来解决集合合并与查找的问题,也常称为并查集。

一、并查集的链表实现

image.png

如上图,并查集可以用链表来实现。

链表实现的并查集,Find-set(a)的时间复杂度是多少?

集合里的每个元素,都指向“集合的句柄”,这样可以使得“查找元素a所在集合S”,即Find-set(a)操作在O(1)的时间内完成。

链表实现的并查集,Union(X, Y)的时间复杂度是多少?

假设有集合:

S1={7,3,1,4}

S2={1,6}

合并S1和S2两个集合,需要做两件事情:

image.png

(1) 第一个集合的尾元素,链向第二个集合的头元素(蓝线1);

(2) 第二个集合的所有元素,指向第一个集合的句柄(蓝线2,3);

合并完的效果是:
image.png

变成了一个更大的集合S1。

集合合并时,将短的链表,往长的链表上接,这样变动的元素更少,这个优化叫做“加权合并”。

画外音:实现的过程中,集合句柄要存储元素个数,头元素,尾元素等属性,以方便上述操作进行。

假设每个集合的平均元素个数是n,Union(X, Y)操作的时间复杂度是O(n)。

能不能Find-set(a)与Union(X, Y)都在O(1)的时间内完成呢?

可以,这就引发了并查集的第二种实现方法。

二、并查集的有根树实现

什么是有根树,和普通的树有什么不同?

常用的set,就是用普通的二叉树实现的,其元素的数据结构是:

element{

         int data;

         element* left;

         element* right;

}

通过左指针与右指针,父亲节点指向儿子节点。

image.png

而有根树,其元素的数据结构是:

element{

         int data;

         element* parent;

}

通过儿子节点,指向父亲节点。

假设有集合:

S1={7,3,1,4}

S2={1,6}

通过如果通过有根树表示,可能是这样的:

image.png

所有的元素,都通过parent指针指向集合句柄,所有元素的Find-set(a)的时间复杂度也是O(1)。

画外音:假设集合的首个元素,代表集合句柄。

有根树实现的并查集,Union(X, Y)的过程如何?时间复杂度是多少?

通过有根树实现并查集,集合合并时,直接将一个集合句柄,指向另一个集合即可。

image.png

如上图所示,S2的句柄,指向S1的句柄,集合合并完成:S2消亡,S1变为了更大的集合。

容易知道,集合合并的时间复杂度为O(1)。

会发现,集合合并之后,有根树的高度变高了,与“加权合并”的优化思路类似,总是把节点数少的有根树,指向节点数多的有根树(更确切的说,是高度矮的树,指向高度高的树),这个优化叫做“按秩合并”。

新的问题来了,集合合并之后,不是所有元素的Find-set(a)操作都是O(1)了,怎么办?

image.png

如图S1与S2合并后的新S1,首次“通过元素6来找新S1的句柄”,不能在O(1)的时间内完成了,需要两次操作。

但为了让未来“通过元素6来找新S1的句柄”的操作能够在O(1)的时间内完成,在首次进行Find-set(“6”)时,就要将元素6“寻根”路径上的所有元素,都指向集合句柄,如下图。

image.png

某个元素如果不直接指向集合句柄,首次Find-set(a)操作的过程中,会将该路径上的所有元素都直接指向句柄,这个优化叫做“路径压缩”。

画外音:路径上的元素第二次执行Find-set(a)时,时间复杂度就是O(1)了。

实施“路径压缩”优化之后,Find-set的平均时间复杂度仍是O(1)。

结论

通过链表实现并查集:

  • Find-set的时间复杂度,是O(1)常数时间
  • Union的时间复杂度,是集合平均元素个数,即线性时间

画外音:别忘了“加权合并”优化。

通过有根树实现并查集:

  • Union的时间复杂度,是O(1)常数时间
  • Find-set的时间复杂度,通过“按秩合并”与“路径压缩”优化后,平均时间复杂度也是O(1)

使用并查集,非常适合解决“微信群覆盖”问题。

思路比结论重要,有收获就是好的。

image.png
架构师之路-分享可落地的技术文章

目录
相关文章
|
2月前
|
人工智能
复制即所得:PasteMD让Markdown粘贴Office不再有格式烦恼
PasteMD是一款高效实用的开源工具,可将剪贴板中的Markdown或网页内容一键转换为Word/WPS/Excel兼容格式,完美保留公式、表格与样式。支持AI生成内容智能粘贴,解决格式错乱难题,提升文档编辑效率,是学生与职场人士的理想助手。
553 2
复制即所得:PasteMD让Markdown粘贴Office不再有格式烦恼
|
2月前
|
JSON 安全 JavaScript
闲鱼商品列表API接口指南
本指南基于逆向分析,提供闲鱼商品列表数据获取的技术方案,适用于关键词、地区、价格等条件筛选。支持网页端GET与移动端POST请求,返回HTML或JSON格式数据,需注意登录态与参数编码,仅用于学习研究。
|
9月前
|
机器学习/深度学习 运维 监控
医疗诊断中的异常检测实战——基于AutoEncoder与One-Class SVM的少样本学习
本文系统性阐述了医疗异常检测的技术革新与工程实现,涵盖从数据处理到模型部署的全流程。针对传统方法标注依赖强、维度灾难及类别不平衡等问题,提出双阶段架构:无监督特征学习结合单分类决策,显著提升早期肺癌检出率37%。文中详细解析了3D Residual AutoEncoder设计、损失函数优化及核函数选择等关键技术,并通过脑卒中检测案例验证性能优势。最终探讨生产环境下的高性能推理与持续学习机制,为多模态融合和可解释性增强提供前沿展望。该方案在少样本场景下表现出色,AUC提升12.5%,假阳性率降低38%,端到端推理速度达800ms/例以下。
225 4
|
3月前
|
JSON 缓存 API
【剪映小助手】向现有草稿中添加关键帧
向现有草稿中添加关键帧。该接口用于在指定的片段上添加关键帧动画,支持多种属性类型的关键帧设置,如位置、缩放、旋转、透明度等。关键帧可以用于创建复杂的动画效果,增强视频的视觉表现力。
|
存储 人工智能 自然语言处理
AI 剧本生成与动画创作解决方案体验报告
AI 剧本生成与动画创作解决方案体验报告
584 40
|
JavaScript
js 保留2位小数
js 保留2位小数
336 124
|
存储 人工智能 缓存
OSS 100Gbps/租户技术解读
本次分享由阿里云资深技术专家罗庆超解读OSS 100Gbps/租户技术,涵盖五个方面:技术概况、后端性能保障、网络接入优化、最后一公里优化及总结展望。介绍了如何通过高性能存储池、网络优化和客户端工具提升性能,确保用户享受高效稳定的对象存储服务,并展望了未来的技术挑战和发展方向。
246 14
|
机器学习/深度学习 搜索推荐 大数据
大数据与教育:学生表现分析的工具
【10月更文挑战第31天】在数字化时代,大数据成为改善教育质量的重要工具。本文探讨了大数据在学生表现分析中的应用,介绍学习管理系统、智能评估系统、情感分析技术和学习路径优化等工具,帮助教育者更好地理解学生需求,制定个性化教学策略,提升教学效果。尽管面临数据隐私等挑战,大数据仍为教育创新带来巨大机遇。
|
数据挖掘 调度 Python
【第十届“泰迪杯”数据挖掘挑战赛】B题:电力系统负荷预测分析 Baseline
第十届“泰迪杯”数据挖掘挑战赛B题的基线解决方案,涉及电力系统负荷预测分析,包括数据读取、特征处理、模型训练和评估,以及使用了LightGBM进行回归预测。
484 3

热门文章

最新文章