mirror of
https://github.com/labuladong/fucking-algorithm.git
synced 2025-07-04 11:22:59 +08:00
leodpen<update> Union-Find算法应用.md
This commit is contained in:
@ -20,6 +20,8 @@
|
||||
|
||||
[990.等式方程的可满足性](https://leetcode-cn.com/problems/surrounded-regions)
|
||||
|
||||
[261.以图判树](https://leetcode-cn.com/problems/graph-valid-tree/)
|
||||
|
||||
**-----------**
|
||||
|
||||
上篇文章很多读者对于 Union-Find 算法的应用表示很感兴趣,这篇文章就拿几道 LeetCode 题目来讲讲这个算法的巧妙用法。
|
||||
@ -250,4 +252,78 @@ boolean equationsPossible(String[] equations) {
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
||||
======其他语言代码======
|
||||
|
||||
第261题的Java代码(提供:[LEODPEN](https://github.com/LEODPEN))
|
||||
|
||||
```java
|
||||
class Solution {
|
||||
|
||||
class DisjointSet {
|
||||
|
||||
int count; // 连通分量的总个数
|
||||
int[] parent; // 每个节点的头节点(不一定是连通分量的最终头节点)
|
||||
int[] size; // 每个连通分量的大小
|
||||
|
||||
public DisjointSet(int n) {
|
||||
parent = new int[n];
|
||||
size = new int[n];
|
||||
// 初为n个连通分量,期望最后为1
|
||||
count = n;
|
||||
for (int i = 0; i < n; i++) {
|
||||
// 初始的连通分量只有该节点本身
|
||||
parent[i] = i;
|
||||
size[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param first 节点1
|
||||
* @param second 节点2
|
||||
* @return 未连通 && 连通成功
|
||||
*/
|
||||
public boolean union(int first, int second) {
|
||||
// 分别找到包含first 和 second 的最终根节点
|
||||
int firstParent = findRootParent(first), secondParent = findRootParent(second);
|
||||
// 相等说明已经处于一个连通分量,即说明有环
|
||||
if (firstParent == secondParent) return false;
|
||||
// 将较小的连通分量融入较大的连通分量
|
||||
if (size[firstParent] >= size[secondParent]) {
|
||||
parent[secondParent] = firstParent;
|
||||
size[firstParent] += size[secondParent];
|
||||
} else {
|
||||
parent[firstParent] = secondParent;
|
||||
size[secondParent] += size[firstParent];
|
||||
}
|
||||
// 连通分量已合并,count减少
|
||||
count--;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param node 某节点
|
||||
* @return 包含该节点的连通分量的最终根节点
|
||||
*/
|
||||
private int findRootParent(int node) {
|
||||
while (node != parent[node]) {
|
||||
// 压缩路径
|
||||
parent[node] = parent[parent[node]];
|
||||
node = parent[node];
|
||||
}
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean validTree(int n, int[][] edges) {
|
||||
// 树的特性:节点数 = 边数 + 1
|
||||
if (edges.length != n - 1) return false;
|
||||
graph_261.Solution.DisjointSet djs = new graph_261.Solution.DisjointSet(n);
|
||||
for (int[] edg : edges) {
|
||||
// 判断连通情况(如果合并的两个点在一个连通分量里,说明有环)
|
||||
if (!djs.union(edg[0], edg[1])) return false;
|
||||
}
|
||||
// 是否全部节点均已相连
|
||||
return djs.count == 1;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
Reference in New Issue
Block a user