Union Find Disjoint Set Data Structure in DSA Javascript - Time & Space Complexity
We want to understand how fast the Union Find data structure works when connecting groups and checking if items belong together.
How does the time needed change as we add more items or connections?
Analyze the time complexity of the following code snippet.
class UnionFind {
constructor(size) {
this.parent = Array(size).fill(0).map((_, i) => i);
this.rank = Array(size).fill(0);
}
find(x) {
if (this.parent[x] !== x) {
this.parent[x] = this.find(this.parent[x]);
}
return this.parent[x];
}
union(x, y) {
let rootX = this.find(x);
let rootY = this.find(y);
if (rootX !== rootY) {
if (this.rank[rootX] < this.rank[rootY]) {
this.parent[rootX] = rootY;
} else if (this.rank[rootX] > this.rank[rootY]) {
this.parent[rootY] = rootX;
} else {
this.parent[rootY] = rootX;
this.rank[rootX]++;
}
}
}
}
This code creates a Union Find structure that groups items and finds their leaders efficiently using path compression and rank.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The
findfunction uses recursion to find the leader of a group and compresses the path. - How many times: Each
unioncallsfindtwice, andfindmay recurse up the tree, but path compression keeps trees shallow.
As we add more items, the time to find leaders grows very slowly because the trees stay flat.
| Input Size (n) | Approx. Operations per find/union |
|---|---|
| 10 | About 4-5 steps |
| 100 | About 6-7 steps |
| 1000 | About 8-9 steps |
Pattern observation: The steps grow very slowly, almost like a flat line, even as input grows large.
Time Complexity: O(α(n)) per operation
This means each find or union operation takes almost constant time, growing so slowly it's practically flat for all real input sizes.
[X] Wrong: "Each find or union takes linear time because it might check many items."
[OK] Correct: Path compression and rank keep the trees very shallow, so operations rarely check many items, making them almost constant time.
Understanding Union Find's time complexity shows you can handle efficient grouping problems, a useful skill in many coding challenges and real-world tasks.
"What if we removed path compression from the find method? How would the time complexity change?"
Practice
Union Find Disjoint Set data structure?Solution
Step 1: Understand the role of Union Find
The Union Find data structure helps keep track of which elements belong to the same group or set.Step 2: Identify its main operation
It supports merging two groups and checking if two elements are in the same group efficiently.Final Answer:
To efficiently track and merge groups of connected elements -> Option AQuick Check:
Union Find = Track and merge groups [OK]
- Confusing Union Find with sorting algorithms
- Thinking it stores key-value pairs like a dictionary
- Assuming it works like a queue or stack
Solution
Step 1: Understand parent array initialization
Each element is initially its own parent, so parent[i] = i for all i.Step 2: Check each option
const parent = [0, 1, 2, 3, 4]; correctly sets parent to [0,1,2,3,4]. const parent = new Array(5).fill(0); fills all with 0, wrong. const parent = new Array(5).fill(-1); fills with -1, wrong. const parent = [1, 2, 3, 4, 5]; starts from 1, wrong index.Final Answer:
const parent = [0, 1, 2, 3, 4]; -> Option BQuick Check:
Parent array = self indices [OK]
- Filling parent array with zeros or -1
- Starting indices from 1 instead of 0
- Not initializing parent array at all
const parent = [0, 1, 2, 3, 4];
function find(x) {
if (parent[x] !== x) {
parent[x] = find(parent[x]);
}
return parent[x];
}
function union(a, b) {
const rootA = find(a);
const rootB = find(b);
if (rootA !== rootB) {
parent[rootB] = rootA;
}
}
union(0, 1);
union(1, 2);
console.log(parent);
What will be printed?Solution
Step 1: Perform union(0, 1)
Find roots: root of 0 is 0, root of 1 is 1. Set parent[1] = 0. Parent becomes [0,0,2,3,4].Step 2: Perform union(1, 2)
Find roots: root of 1 is find(0) = 0, root of 2 is 2. Set parent[2] = 0. Parent becomes [0,0,0,3,4].Final Answer:
[0, 0, 0, 3, 4] -> Option AQuick Check:
Union updates parents to root 0 [OK]
- Not applying path compression in find
- Confusing which root becomes parent
- Assuming parent array stays unchanged
const parent = [0, 1, 2, 3];
function find(x) {
if (parent[x] === x) return x;
return find(parent[x]);
}
function union(a, b) {
const rootA = find(a);
const rootB = find(b);
if (rootA !== rootB) {
parent[rootA] = rootB;
}
}
union(0, 1);
union(1, 2);
console.log(parent);
What is the bug in this code?Solution
Step 1: Examine the find function
The find recurses to the root but lacks path compression: it should set parent[x] = find(parent[x]) before returning when parent[x] !== x.Step 2: Verify other options
Find returns correctly. Parent is initialized properly as self-references. Union direction (parent[rootA] = rootB) is valid.Final Answer:
Missing path compression in find function -> Option DQuick Check:
Path compression: parent[x] = find(parent[x]) [OK]
- Ignoring missing path compression
- Thinking find lacks return statement
- Assuming parent array is wrong when it's correct
union(0, 1); union(2, 3); union(4, 5); union(1, 2); union(0, 4);How many distinct sets remain?
Solution
Step 1: Perform unions step-by-step
union(0,1) merges sets {0},{1} -> {0,1} union(2,3) merges {2},{3} -> {2,3} union(4,5) merges {4},{5} -> {4,5}Step 2: Continue unions
union(1,2) merges {0,1} and {2,3} -> {0,1,2,3} union(0,4) merges {0,1,2,3} and {4,5} -> {0,1,2,3,4,5}Step 3: Count distinct sets
All elements are connected in one set.Final Answer:
1 -> Option CQuick Check:
All unions connect all elements [OK]
- Counting each union as a new set
- Not merging transitive connections
- Forgetting that union merges sets fully
Ready to prove it?
Pass the test and this pattern moves unknown
