1. 定义

维基百科:并查集(英文:Disjoint-set data structure,直译为不交集数据结构)是一种数据结构,用于处理一些不交集(Disjoint sets,一系列没有重复元素的集合)的合并及查询问题。并查集支持如下操作:

  • 查询:查询某个元素属于哪个集合,通常是返回集合内的一个“代表元素”。这个操作是为了判断两个元素是否在同一个集合之中。
  • 合并:将两个集合合并为一个。
  • 添加:添加一个新集合,其中有一个新元素。添加操作不如查询和合并操作重要,常常被忽略。

2. 并查集代码

  1. static class UF{
  2. private int[] parent;
  3. private int count;
  4. public UF(int n) {
  5. parent = new int[n];
  6. for(int i = 0;i < n;i++) {
  7. parent[i] = i;
  8. }
  9. this.count = n;
  10. }
  11. public int find(int x) {
  12. while(parent[x] != x) {
  13. parent[x] = parent[parent[x]];
  14. x = parent[x];
  15. }
  16. return x;
  17. }
  18. public boolean isConnect(int x,int y) {
  19. int xRoot = find(x);
  20. int yRoot = find(y);
  21. return xRoot == yRoot;
  22. }
  23. public void union(int x,int y) {
  24. int xRoot = find(x);
  25. int yRoot = find(y);
  26. parent[x] = yRoot;
  27. count--;
  28. }
  29. public int getCount(){
  30. return count;
  31. }
  32. }

2.1 代码解读

并查集代码使用一个数组模拟节点集合组成的森林,parent[x]的值代表节点x的父亲节点为parent[x]count代表连通分量的数量。主要操作有findunion,作用分别是查询某个节点的根节点和连通两个节点。find函数中使用了路径压缩来优化,使得并查集的合并操作和查询操作都可以做到常数级别的时间复杂度。

题目

你有一个包含 n 个节点的图。给定一个整数 n 和一个数组 edges ,其中 edges[i] = [ai, bi] 表示图中 ai 和 bi 之间有一条边。

返回 图中已连接分量的数目 。

示例 1:

并查集 - 图1

输入: n = 5, edges = [[0, 1], [1, 2], [3, 4]]
输出: 2
示例 2:

并查集 - 图2

输入: n = 5, edges = [[0,1], [1,2], [2,3], [3,4]]
输出: 1

  1. public class Leetcode323 {
  2. public int countComponents(int n, int[][] edges) {
  3. UF uf = new UF(n);
  4. for(int[] edge:edges) {
  5. if(!uf.isConnect(edge[0],edge[1])) {
  6. uf.union(edge[0],edge[1]);
  7. }
  8. }
  9. return uf.getCount();
  10. }
  11. public static void main(String[] args) {
  12. int[][] edges = {{0,1},{1,2},{3,4}};
  13. Leetcode323 leetcode323 = new Leetcode323();
  14. System.out.println(leetcode323.countComponents(5,edges));
  15. }
  16. static class UF{
  17. private int[] parent;
  18. private int count;
  19. public UF(int n) {
  20. parent = new int[n];
  21. for(int i = 0;i < n;i++) {
  22. parent[i] = i;
  23. }
  24. this.count = n;
  25. }
  26. public int find(int x) {
  27. while(parent[x] != x) {
  28. parent[x] = parent[parent[x]];
  29. x = parent[x];
  30. }
  31. return x;
  32. }
  33. public boolean isConnect(int x,int y) {
  34. int xRoot = find(x);
  35. int yRoot = find(y);
  36. return xRoot == yRoot;
  37. }
  38. public void union(int x,int y) {
  39. int xRoot = find(x);
  40. int yRoot = find(y);
  41. parent[x] = yRoot;
  42. count--;
  43. }
  44. public int getCount(){
  45. return count;
  46. }
  47. }
  48. }