标签:comm 父节点 输出 就是 计组 路径压缩 组件 扁平化 mon
一、场景
并查集多数是用来解决连通性问题的
如至少修建几条路可以使所有路口可以相通
把互通的路口当做一个群组,那问题就是有几个这样的群组
如有N个群组 那至少修N-1条路 就可以把所有路口相连。
二、使用
并查集分两步
1、合并
合并就是把相连的多个节点划到一个群组中
可以定义数组parent[] 表示对应节点的父节点索引。
这样不断查询节点A的父节点,可以找到组先节点(父节点就是本身的节点)
所谓相连节点就是设置同一个组先节点
2、查询
查询两个节点是否相连,只要判断各自的组先节点是否相同,如果相同,就是相连的
在查询的过程中 可以路径压缩(节点的父节点直接指向组先节点),使结构扁平化,提升查询效率
三、示例
如leecode第952题:按公因数计算最大组件大小
这个问题就是一个并查集的问题,只要知道哪些数是一组的,再求出最大一组的元素个数即可
解题如下
class Solution { private class UnionFindUtil { // 对应父节点位置 private int[] parent; // 初始化 每个元素的父节点索引==自身索引 public UnionFindUtil(int n) { parent = new int[n]; for (int i = 0; i < n; i++) { parent[i] = i; } } // 查找 public int find(int x) { if (parent[x] == x) { return x; } // 路径压缩 parent[x] = find(parent[x]); return parent[x]; } // 合并 public void union(int x, int y) { int rootX = find(x); int rootY = find(y); if (rootX != rootY) { parent[rootX] = rootY; } } } public int largestComponentSize(int[] A) { int maxVal = 0; for (int num : A) { maxVal = Math.max(maxVal, num); } // 使用质数来判断是否两连 UnionFindUtil unionFind = new UnionFindUtil(maxVal + 1); for (int num : A) { double upBound = Math.sqrt(num); for (int i = 2; i <= upBound; i++) { if (num % i == 0) { unionFind.union(num, i); unionFind.union(num, num / i); } } } // 找出最大者 int[] cnt = new int[maxVal + 1]; int res = 0; for (int num : A) { int root = UnionFindUtil.find(num); // 统计组先节点出现的次数 每次加一 cnt[root]++; res = Math.max(res, cnt[root]); } return res; } }
标签:comm 父节点 输出 就是 计组 路径压缩 组件 扁平化 mon
原文地址:https://www.cnblogs.com/yangfei629/p/12507587.html