并查集(Union-Find)入门指南
什么是并查集?
并查集是一种简洁优雅的数据结构,主要用于处理元素分组的问题。它的特点是:
- 可以高效地管理一系列不相交的集合
- 支持两个核心操作:合并(Union)和查找(Find)
- 在前端开发中常用于:社交网络、网络连接、组件状态管理等场景
核心API设计
- 构造函数: 初始化并查集
- find(): 查找元素所属的组
- union(): 合并两个组
- isSame(): 判断两个元素是否在同一组
- getCount(): 获取当前分组数量
代码实现
js
class UnionFind {
constructor(n) {
this.parent = [] // 存储节点的父节点
this.size = [] // 存储每个根节点的子树大小
this.count = 0 // 当前分组数量
this.init(n)
}
// 初始化
init(n) {
this.parent = Array.from({length: n}, (_, i) => i) // 初始时每个节点指向自己
this.size = new Array(n).fill(1)
this.count = n
}
// 查找节点所属的组(根节点)
find(node) {
while (node !== this.parent[node]) {
// 路径压缩优化: 将查找路径上的所有节点直接指向根节点
this.parent[node] = this.parent[this.parent[node]]
node = this.parent[node]
}
return node
}
// 合并两个组
union(left, right) {
const leftRoot = this.find(left)
const rightRoot = this.find(right)
if (leftRoot !== rightRoot) {
// 按秩合并优化: 将小树合并到大树下
if (this.size[leftRoot] < this.size[rightRoot]) {
this.parent[leftRoot] = rightRoot
this.size[rightRoot] += this.size[leftRoot]
} else {
this.parent[rightRoot] = leftRoot
this.size[leftRoot] += this.size[rightRoot]
}
this.count--
return true
}
return false
}
// 其他辅助方法...
}性能优化
- 路径压缩: 在find操作时将路径上的节点直接指向根节点,降低树的高度
- 按秩合并: 合并时将小树合并到大树下,保持树的平衡
实际应用场景
- 好友关系网络
- 网站账号合并
- React组件状态管理
- 网络连接判断
复杂度分析
- 时间复杂度: 接近O(1) [使用路径压缩和按秩合并后]
- 空间复杂度: O(n)
练习题推荐
- LeetCode 547: 省份数量
- LeetCode 200: 岛屿数量
- LeetCode 684: 冗余连接