Union Find structy
https://structy.net/problems/premium/intro-to-union-find
union find - very performant when optimized
deals with connected components or "islands"
union nodes:
- find - node's parent
- union - connect parents

Not optimized solution:
const find = (roots, node) => {
if (node === roots[node]) {
return node;
}
return find(roots, roots[node]);
};
const union = (roots, nodeA, nodeB) => {
const rootA = find(roots, nodeA);
const rootB = find(roots, nodeB);
roots[rootB] = rootA;
};
const countComponents = (n, edges) => {
const roots = [];
for (let i = 0; i < n; i += 1) {
roots.push(i);
}
for (let edge of edges) {
const [ nodeA, nodeB ] = edge;
union(roots, nodeA, nodeB);
}
let count = 0;
for (let i = 0; i < n; i += 1) {
if (i === roots[i]) {
count += 1;
}
}
return count;
};
Optimized code
const find = (roots, node) => {
if (roots[node] === node) {
return node;
}
const found = find(roots, roots[node]);
roots[node] = found; //path compression
return found;
};
const union = (roots, sizes, nodeA, nodeB) => {
const rootA = find(roots, nodeA);
const rootB = find(roots, nodeB);
if (rootA === rootB) {
return;
}
//union by size
if (sizes[rootA] >= sizes[rootB]) {
roots[rootB] = rootA;
sizes[rootA] += sizes[rootB];
} else {
roots[rootA] = rootB;
sizes[rootB] += sizes[rootA];
}
};
const countComponents = (n, edges) => {
const roots = [];
const sizes = [];
for (let i = 0; i < n; i += 1) {
roots.push(i);
sizes.push(1);
}
for (let edge of edges) {
const [a, b] = edge;
union(roots, sizes, a, b);
}
let count = 0;
for (let i = 0; i < n; i += 1) {
if (i === roots[i]) {
count += 1;
}
}
return count;
};
Problems: