【算法笔记】并查集详解

🚀 并查集(Union-Find)详解:原理、实现与优化

并查集(Union-Find)是一种非常高效的数据结构,用于处理动态连通性问题,即判断若干个元素是否属于同一个集合,并支持集合合并操作。它在图算法中(如 Kruskal 最小生成树)、朋友圈统计、网络连通性判断等场景中非常常见。

🧠 并查集的核心功能

  • find(x) :查找元素 x 所在集合的代表(也叫"根节点")
  • union(x, y) :将元素 xy 所在的两个集合合并
  • parent[x]:记录每个元素的"父亲",通过父亲链条找祖先(树结构)

🧩 并查集基本结构

python 复制代码
n = 5
parents = list(range(n + 1))  # parents[i] = i,0号位不使用

🔍 基本实现:find 和 union

python 复制代码
def find(x):
    if parents[x] == x:
        return x
    else:
        return find(parents[x])
python 复制代码
def union(x, y):
    root_x = find(x)
    root_y = find(y)
    if root_x == root_y:
        return False
    parents[root_y] = root_x
    return True

🧠 类比记忆

  • 每个元素的 parent 就像是它的"爸爸"
  • find(x) 就是往上找老祖宗
  • union(x, y) 就是两个家族联姻,把一个家族并进另一个

⚡ 并查集优化技巧(路径优化):路径压缩优化

查询时顺便把路径上所有的节点都指向大族长,一次find后这条路径的深度为1

python 复制代码
def find(x):
    if x != parents[x]:
        parents[x] = find(parents[x])
    return parents[x]

🧱 并查集优化技巧(合并优化):按秩合并 & 按大小合并

🔢 按大小合并(Union by Size)

小家族归大家族,大的当族长

python 复制代码
size = [1] * (n + 1)

def union(x, y):
    rx, ry = find(x), find(y)
    if rx == ry:
        return False
    if size[rx] < size[ry]:
        parents[rx] = ry
        size[ry] += size[rx]
    else:
        parents[ry] = rx
        size[rx] += size[ry]
    return True

🏷️ 按秩合并(Union by Rank)

辈分高的当族长

python 复制代码
rank = [0] * (n + 1)

def union(x, y):
    rx, ry = find(x), find(y)
    if rx == ry:
        return False
    if rank[rx] < rank[ry]:
        parents[rx] = ry
    elif rank[rx] > rank[ry]:
        parents[ry] = rx
    else:
        parents[ry] = rx
        rank[rx] += 1
    return True

💡 组合使用建议

最推荐的并查集配置是:

路径压缩 + 按秩合并 或 按大小合并

能达到几乎 O(1) 的查询和合并效率。

📚 应用场景

  • Kruskal 最小生成树算法
  • 网络连通性判断
  • 动态连通块个数统计
  • 岛屿数量(LeetCode 200)
  • 冗余连接(LeetCode 684)
  • 朋友圈数量(LeetCode 547)

🎯 总结

术语 含义
find(x) 找出 x 所属集合的根节点
union(x, y) 合并 x 和 y 的集合(若不属于同一集合)
路径压缩 加快 find 查询效率
按秩/按大小 优化合并策略,防止退化
树的结构 集合之间的连接关系

并查集看起来简单,背后其实是极高效的数据结构设计。建议掌握它,并尝试应用到图论、集合问题中去!


🧩 常见练习题

✅ 基础入门题

题号 题目名称 链接 简介
200 岛屿数量 LeetCode 200 判断二维网格中有多少个连通块
684 冗余连接 LeetCode 684 找出图中导致环的边
1319 连通网络的操作次数 LeetCode 1319 判断有多少连通块,以及最少连接次数

🧠 中级应用题

题号 题目名称 链接 简介
1202 交换字符串中的元素 LeetCode 1202 使用并查集形成交换组,对组内排序
721 账户合并 LeetCode 721 通过邮箱合并属于同一用户的账户
323 无向图中连通分量的数目 LeetCode 323 通用连通块计数问题

🔍 进阶与变种题

题号 题目名称 链接 简介
399 除法求值 LeetCode 399 带权并查集:维护节点之间的比例关系
547 省份数量(等价朋友圈问题) LeetCode 547 判断有多少朋友圈/省份
990 等式方程的可满足性 LeetCode 990 并查集维护等式约束

📌 推荐练习顺序

  1. 200 - 岛屿数量
  2. 684 - 冗余连接
  3. 1319 - 连通网络的操作次数
  4. 547 - 省份数量
  5. 1202 - 字符串交换
  6. 721 - 邮箱合并
  7. 399 - 除法求值
  8. 990 - 等式方程可解性

🧠 建议掌握:

  • 基础并查集结构(find, union
  • 路径压缩优化
  • 带权并查集(维护差值、比例等信息)
  • 一维映射(如坐标 → 编号)
相关推荐
aflyingwolf_pomelo9 分钟前
波束形成(BF)从算法仿真到工程源码实现-第四节-最小方差无失真响应波束形成(MVDR)
人工智能·算法·信号处理
zhaoyqcsdn13 分钟前
Eigen库的core模块源码阅读笔记
人工智能·经验分享·笔记·算法
互联网搬砖老肖14 分钟前
21 天 Python 计划:MySQL索引机制从基础到应用
python·mysql·adb
weixin_4284984924 分钟前
将三维非平面点集拆分为平面面片的MATLAB实现
算法·matlab
瀚海澜生24 分钟前
链表系列进阶攻略(三):拆解 LRU 与分割链表,突破链表解题瓶颈
后端·算法
一只鱼^_26 分钟前
第十六届蓝桥杯大赛软件赛省赛 C/C++ 大学B组
c语言·c++·算法·贪心算法·蓝桥杯·深度优先·图搜索算法
说码解字27 分钟前
快速排序算法及其优化
算法
Lounger6631 分钟前
107.二叉树的层序遍历II- 力扣(LeetCode)
python·算法·leetcode
Code_流苏31 分钟前
《Python星球日记》第25天:Pandas 数据分析
python·数据分析·pandas·数据聚合·时间序列
IT猿手32 分钟前
动态多目标优化:基于可学习预测的动态多目标进化算法(DIP-DMOEA)求解CEC2018(DF1-DF14),提供MATLAB代码
学习·算法·matlab·动态多目标优化·动态多目标进化算法