并查集算法应用:连通、合并与判环

从无向图判环、账户合并、岛屿数量和等式约束理解并查集的算法应用边界。

已发布文章计算机基础入门6 分钟阅读发布于 2026年9月1日更新于 2026年9月15日
文章目录
  1. 并查集适合什么问题
  2. 基础模板
  3. 无向图判环
  4. 账户合并
  5. 岛屿数量
  6. 等式约束
  7. 并查集复杂度
  8. 常见错误
  9. 面试题
  10. 小结
知识目录数据结构与算法:从基础到工程实践44 / 77
LOCAL NOTE高亮并记笔记
0 / 1000 · 只保存在这台设备
READER NOTES并查集算法应用:连通、合并与判环》的本机笔记

我真正开始理解“并查集算法应用:连通、合并与判环”,不是在背完某段代码之后,而是在一次次写错之后。最明显的问题是:并查集代码很短,我却一度只会照着模板写 parent 数组,不清楚它为什么适合动态合并,却不擅长删除和恢复路径。把这些错误重新摊开来看,我才找到比口诀更可靠的理解方式。

并查集在数据结构篇里已经讲过基本结构:父数组、路径压缩、按秩合并。到了算法篇,我们更关心它能解决哪些问题。

并查集最适合回答一句话:两个元素现在是否属于同一个集合?

并查集适合什么问题

并查集应用

图:并查集用代表元判断两个元素是否属于同一个集合

常见应用:

  • 无向图连通分量。
  • 动态合并集合。
  • 判断新增边是否形成环。
  • Kruskal 最小生成树。
  • 岛屿数量动态变化。
  • 等式约束一致性。
  • 账户合并。

它不擅长:

  • 删除边。
  • 查询两点之间具体路径。
  • 维护有向可达关系。
  • 频繁拆分集合。

基础模板

class UnionFind {
    private final int[] parent;
    private final int[] size;
    private int count;

    UnionFind(int n) {
        parent = new int[n];
        size = new int[n];
        count = n;
        for (int i = 0; i < n; i++) {
            parent[i] = i;
            size[i] = 1;
        }
    }

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

    boolean union(int a, int b) {
        int ra = find(a), rb = find(b);
        if (ra == rb) return false;
        if (size[ra] < size[rb]) {
            int t = ra; ra = rb; rb = t;
        }
        parent[rb] = ra;
        size[ra] += size[rb];
        count--;
        return true;
    }

    boolean connected(int a, int b) {
        return find(a) == find(b);
    }

    int count() {
        return count;
    }
}

union 返回 false 表示两个点原本已经连通,这在判环时很有用。

无向图判环

给定无向图边列表,如果某条边的两个端点已经连通,再加入这条边就会形成环。

boolean hasCycle(int n, int[][] edges) {
    UnionFind uf = new UnionFind(n);
    for (int[] e : edges) {
        if (!uf.union(e[0], e[1])) {
            return true;
        }
    }
    return false;
}

注意:这个方法适合无向图。有向图判环通常用 DFS 三色标记或拓扑排序。

账户合并

如果两个账号拥有相同邮箱,就认为属于同一个人。可以把账号编号作为集合元素,把共享邮箱的账号 union 起来。

思路:

  1. 遍历每个账号的邮箱。
  2. 邮箱第一次出现时记录所属账号。
  3. 邮箱再次出现时,把两个账号合并。
  4. 最后按代表元收集邮箱。

这类问题体现了并查集的工程价值:它把“多条关系连接成多个群组”变得很自然。

岛屿数量

二维网格里,每个陆地格子可以看成一个节点,相邻陆地 union 到一起。最后集合数量就是岛屿数量。

动态岛屿问题中,格子会逐步从水变成陆地。每加入一个陆地,岛屿数先加一,再和周围陆地合并,成功合并一次岛屿数减一。

等式约束

例如:

a == b
b == c
a != c

先把所有等式合并,再检查不等式两端是否已经连通。如果连通,就矛盾。

这个模式常见于约束一致性判断。

并查集复杂度

路径压缩 + 按大小合并后,单次操作的均摊复杂度接近常数,通常写作 O(α(n))α(n) 是反阿克曼函数,在现实数据规模下可以近似看成小于 5。

但不要因此把并查集当万能结构。它快,是因为它只回答集合代表元,不回答集合内部路径细节。

常见错误

  • 只压缩路径,不按大小合并,极端情况下树仍可能变高。
  • 忘记 count--
  • 把有向图判环错误套用并查集。
  • 需要路径信息的问题误用并查集。
  • 二维坐标映射成一维编号时下标写错。

面试题

  1. 并查集适合解决什么问题?
  2. 路径压缩有什么作用?
  3. 为什么无向图判环可以用并查集?
  4. 有向图判环为什么不能直接套并查集?
  5. 动态岛屿数量如何维护?

小结

并查集是一种非常克制但强大的结构。它不关心路径,只关心集合。只要问题能转化成“合并关系”和“判断是否同组”,它就非常合适;如果问题要查询方向、路径、删除或拆分,就要换别的工具。

JARVIS · 当前文章

有哪里没看懂?可以只问这篇。

Jarvis 会限定在《并查集算法应用:连通、合并与判环》及其公开关联内容中检索,并把引用定位回原文章节。

JARVIS / ARTICLE针对《并查集算法应用:连通、合并与判环》提问
当前范围并查集算法应用:连通、合并与判环不会悄悄扩大到全站
0 / 1000

准备好了。当前只会围绕并查集算法应用:连通、合并与判环回答。

READER SIGNAL

这篇内容对你有帮助吗?

不需要登录。你的反馈会直接进入作者待处理列表。