Path Compression in Union Find in DSA Javascript - Time & Space Complexity
We want to understand how fast the "find" operation runs when we use path compression in Union Find.
How does the time to find a set leader change as we do more operations?
Analyze the time complexity of the following code snippet.
function find(parent, x) {
if (parent[x] !== x) {
parent[x] = find(parent, parent[x]);
}
return parent[x];
}
This code finds the leader of element x and compresses the path to speed up future finds.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursive calls to find until the root leader is found.
- How many times: At most once per node on the path from x to the root, but path compression shortens future calls.
Initially, the path to the root might be long, so find takes more steps. But each find shortens paths, making future finds faster.
| Input Size (n) | Approx. Operations per Find |
|---|---|
| 10 | Up to 4-5 steps initially, then close to 1 step |
| 100 | Up to 10-15 steps initially, then fewer steps over time |
| 1000 | Up to 20-30 steps initially, then almost constant time |
Pattern observation: The cost per find decreases over time, approaching almost constant time.
Time Complexity: O(α(n)) (Inverse Ackermann function)
This means each find operation runs almost in constant time for all practical input sizes.
[X] Wrong: "Each find always takes time proportional to the height of the tree."
[OK] Correct: Path compression flattens the tree, so after some finds, the height effectively becomes very small, making future finds much faster.
Understanding path compression's time complexity shows you how clever tweaks make algorithms efficient in practice, a skill valued in problem solving.
"What if we removed path compression? How would the time complexity of find change?"
Practice
path compression in the Union Find data structure?Solution
Step 1: Understand the role of path compression
Path compression is used during thefindoperation to make future queries faster by making nodes point directly to the root.Step 2: Identify the effect on the tree structure
This flattens the tree, reducing the height and speeding up subsequentfindcalls.Final Answer:
To speed up thefindoperation by flattening the tree structure -> Option AQuick Check:
Path compression = flatten tree = faster find [OK]
- Confusing path compression with union by rank
- Thinking it merges sets without root checks
- Believing it initializes data structures
find function with path compression in JavaScript?Solution
Step 1: Identify path compression in the code
function find(x) { if (parent[x] !== x) parent[x] = find(parent[x]); return parent[x]; } updatesparent[x]to the root during recursion, which is path compression.Step 2: Compare other options
function find(x) { while (parent[x] !== x) x = parent[x]; return x; } uses iteration but no path compression. function find(x) { if (parent[x] === x) return x; else return find(parent[x]); } uses recursion but no assignment toparent[x]. function find(x) { parent[x] = x; return x; } resets parent incorrectly.Final Answer:
function find(x) { if (parent[x] !== x) parent[x] = find(parent[x]); return parent[x]; } -> Option BQuick Check:
Path compression requires parent update = function find(x) { if (parent[x] !== x) parent[x] = find(parent[x]); return parent[x]; } [OK]
- Missing parent update for path compression
- Using iteration without compression
- Resetting parent incorrectly
console.log(parent) after calling find(3)?
let parent = [0, 0, 1, 2, 4];
function find(x) {
if (parent[x] !== x) parent[x] = find(parent[x]);
return parent[x];
}
find(3);
console.log(parent);Solution
Step 1: Trace the find(3) call
find(3) checks parent[3] = 2, not 3, so calls find(2). find(2) checks parent[2] = 1, not 2, so calls find(1). find(1) checks parent[1] = 0, not 1, so calls find(0). find(0) returns 0 since parent[0] = 0.Step 2: Apply path compression updates
parent[1] = 0, parent[2] = 0, parent[3] = 0 after recursion. But initial array was [0,0,1,2,4]. After updates, parent becomes [0,0,0,0,4]. However, the code only updates parent[x] during recursion. The first call updates parent[3] = find(2) = 0, parent[2] = find(1) = 0, parent[1] = find(0) = 0. So final parent array is [0,0,0,0,4].Final Answer:
[0, 0, 0, 0, 4] -> Option AQuick Check:
Path compression sets parents to root = [0,0,0,0,4] [OK]
- Not updating all parents during recursion
- Confusing parent indices
- Assuming no change after find
find function implementing path compression:
function find(x) {
if (parent[x] === x) return x;
else find(parent[x]);
}Solution
Step 1: Check the recursive calls and returns
The else branch callsfind(parent[x])but does not return its result, so the function returns undefined for non-root nodes.Step 2: Confirm missing return causes bug
Without returning the recursive call, the function fails to return the root, breaking the find operation.Final Answer:
Missing return statement in the else branch -> Option DQuick Check:
Recursive calls must return values [OK]
- Forgetting to return recursive call result
- Misunderstanding base case
- Thinking iteration is required
parent = [0, 0, 2, 2, 4] and rank = [0, 1, 0, 0, 0]. After performing union(3, 4) and then find(3), what will be the updated parent array assuming path compression is applied in find?Solution
Step 1: Perform union(3, 4)
Find roots: find(3) = 2, find(4) = 4. Since rank[2] = 0 and rank[4] = 0, attach 3's root (2) to 4. So parent[2] = 4.Step 2: Perform find(3) with path compression
find(3) calls find(2), which calls find(4). find(4) returns 4. Path compression sets parent[2] = 4 and parent[3] = parent[2] = 4.Final Answer:
[0, 0, 4, 4, 4] -> Option CQuick Check:
Union attaches root, find compresses path [OK]
- Not updating parent after union
- Ignoring path compression updates
- Confusing rank usage
Ready to prove it?
Pass the test and this pattern moves unknown
