Union Find
Last updated
Was this helpful?
Last updated
Was this helpful?
n is the number of groups. When connect two node, reduce the number of groups, what left is result.
T: O(n^2) - O(n*) S: O(n)
Valid Tree: 就是看有没有cycle, 找出每个点的Root,如果if (rootX == rootY) return false
. 还要Check一下edges.length == n - 1
。 有点像685. Redundant Connection II
很经典的题。主要要看2D matrix 和1D array的对应位置。是i * width + j。
值得注意的是Count:
int count = results.isEmpty() ? 1 : results.get(results.size() - 1) + 1;
然后Union一次count--;
The stones on the same col and same row is an island, therefore actually this is a number of islands problem. The total number of stones minus the "number of islands" equals to the number of stones to remove. Therefore the problem becomes to find all connected number of islands. This can be achieved by DFS (O(n^2)) or UnionFind (O(n)).
问a / b = 2.0, b / c = 3.0.
queries are: a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ? .
return [6.0, 0.5, -1.0, 1.0, -1.0 ].
求出a, b, c作为分子和分母的关系
建一个Map<String, Integer> 把每个Word和它的位置放进去。a:0, b:1, c:2
建len个Node用来做UF
Iterate over all words in equation, get roots of each node, set parent and value
nodes[root2].parent = root1;
nodes[root2].value = nodes[k1].value * values[i] / nodes[k2].value;
Iterate over queries:
Integer k1 = mIdTable.get(queries[i][0]);
Integer k2 = mIdTable.get(queries[i][1]);
if (k1 == null || k2 == null) result[i] = -1.0d;
else {
int root1 = find(nodes, k1);
int root2 = find(nodes, k2);
if (root1 != root2) result[i] = -1.0d;
else result[i] = nodes[k2].value / nodes[k1].value;
}
Two cases to find redundant connection for directed graph:
A node has more than one parents
There is a loop
Therefore 2 candidates are needed. Can1 represents case1, can2 represents case2, else union. If both issues present, then the answer should be the first edge which results in "multiple parents" issue.
UnionFind uf = new UnionFind(n);
建一个HashMap<String, Integer>, 把所有的Email存进去: Value is Index. uf.union(preIndex, i) if preIndex is in map.
建一个HashMap<Integer, Set<String>> ufMap, store each index and its associated emails. This is by finding each individual roots and add value to its set.
Convert and output result:
建一个HashMap, 把所有的Pair存进去,A:A and B:B, 并且Union A和B
private void union(String one, String two) {
String p1 = find(one);
String p2 = find(two);
map.put(p1, p2);
}
循环input array,如果有root不相等的直接return false;
row.length : number of ppl, N = row.length / 2: number of couples
Create an array to host relation: int[] groups = new int[row.length];
Groups = [0,0,1,1,2,2,3,3….];
Get person1 and person 2, and couple1 = person1 / 2, couple2 = person2 / 2
If couple1 != couple2, find roots of person, union person1 and person2, count swap++;
couple1 = person1 / 2 非常精髓
FIND & UNION are different as typical:
private int find(int p, int[] A) {
return A[p];
}
private void union(int p, int q, int[] A) {
int rootP = find(p, A);
for (int i = 0; i < A.length; i++) {
if (A[i] == rootP) A[i] = find(q, A);
}
}
BFS + PQ, DFS 都可以做。UF的这个非常精髓,尤其是!uf.isConnected(0, N * N - 1), 在不联通的情况下一直查找和Union,直到联通为止。
从2d到1d转换,new int[N ^ 2], index from 0 to N ^ 2 - 1.
Origin: i * N + j
上下左右:
Up: i * N - N + j
Down: i * N + N + j
Left: i * N + j - 1
Right: i * N + j + 1
int time = 0;
while (!uf.isConnected(0, N * N - 1)) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (grid[i][j] > time) continue;
if (i < N - 1 && grid[i + 1][j] <= time) uf.union(i * N + j, i * N + j + N);
if (j < N - 1 && grid[i][j + 1] <= time) uf.union(i * N + j, i * N + j + 1);
}
}
time++;
}
用Size来统计每个砖联通多少砖
We'll also include dsu.top, which tells us the size of the "roof", or the component connected to the top edge. We use an ephemeral "source" node with label M * N where all nodes on the top edge (with row number 0) are connected to the source node.
屋顶的问题很复杂,每找到一个点都要考虑是不是和屋顶链接。
需要从后忘前算,先算最后hit的,然后一点一点往前。
每一步都用UF的Size统计一下。
Iterate through all nodes, union i, j where node == 1
Initialize ‘count’ array to store root of each malware nodes, count[root]++
Iterate through initial, find root of each one, if count[root] == 1, refresh ans and ansSize by condition highlighted. RootSize > ansSize && rootSize == ansSize && node < ans
If ans = -1, assign ans as min of all nodes
int[] count = new int[N];
for (int node : initial) {
count[uf.find(node)]++;
}
int ans = -1, ansSize = -1;
for (int node : initial) {
int root = uf.find(node);
if (count[root] == 1) {
int rootSize = uf.size(root);
if (rootSize > ansSize || (rootSize == ansSize && node < ans)) {
ansSize = rootSize;
ans = node;
}
}
}
Ini a ‘clean’ array, set value to 0 if it is an initial, 1 if not an initial.
Iterate over nodes and union all nodes.
Union relation between i and j, use uf.union(stone[0], stone[1] + 10000), since
0 <= stones[i][j] < 10000.
Set a set and put in all roots of i. Return N - seen.size();
UF solution2:
UnionFind uf = new UnionFind(stones);
int total = stones.length;
for(int[] stone: stones) {
uf.union(stone[0], stone[1] + 10000);
}
return total - uf.getCount();
UF {
for(int[] stone: stones) {
int i = stone[0], j = stone[1];
if(parents[i] == -1) count++;
parents[i] = i;
if(parents[j + 10000] == -1) count++;
parents[j + 10000] = j + 10000;
}
}
先把所有100000以内的Prime number算出来
For A[] 里面的每个数: 质数分解, A[i] 除以p, 如果p在PrimeToIndex里,把Prime和A里面数的Index连上,Union(PrimeToIndex[p], 和i)
Update PrimeToIndex: PrimeToIndex[p] = i
分到底了就break:
while (a % p == 0) a /= p;
if (a == 1) break;
用个HashMap来存PrimeToIndex:
Map<Integer, Set<Integer>> prime2Idx
Map里存 质数:Array里所有可以用这个用质数分的数的Index
for (int i = 0; i < N; i++) par[i] = i;
Arrays.fill(cnt, 1);
int max = 1;
for (Set<Integer> s : prime2Idx.values()) {
int fir = s.iterator().next();
for (int idx : s) {
union(idx, fir);
max = Math.max(cnt[find(idx)],max);
}
}
return max;
循环所有Map里的Values,Union所有的Index并同时取Max
一个正方形是四个点,N * N个点就要建立(N + 1) * (N + 1)个点的UF array
If input is ‘ ’, we do nothing;
If input is ‘/’, we connect lower left vertex with upper right vertex;
If input is ‘\’, we connect upper left vertex with lower right vertex.
for (int row = 0; row < n; row++) {
for (int col = 0; col < n; col++) {
char op = grid[row].charAt(col);
if (op == '/') {
if (uf.isConnected(row, col + 1, row + 1, col))
cnt += 1;
uf.union(row, col + 1, row + 1, col);
} else if (op == '\\') {
if (uf.isConnected(row, col, row + 1, col + 1))
cnt += 1;
uf.union(row, col, row + 1, col + 1);
}
}
}
既然是找小写字母的关系,就建26位的Array,并Union如果是“==”的,再loop一遍,找出不符合的” != “
int[] uf = new int[26];
public boolean equationsPossible(String[] equations) {
for (int i = 0; i < 26; ++i) uf[i] = i;
for (String e : equations)
if (e.charAt(1) == '=')
uf[find(e.charAt(0) - 'a')] = find(e.charAt(3) - 'a');
for (String e : equations)
if (e.charAt(1) == '!' && find(e.charAt(0) - 'a') == find(e.charAt(3) - 'a'))
return false;
return true;
}
public int find(int x) {
if (x != uf[x]) uf[x] = find(uf[x]);
return uf[x];
}
,
先预处理,建UF的时候n要加1,把所有的点都Union到0。不管怎样,都要把四个方向的点都Union到Curt点上,还要加上Size。
Prime Factorization