Bird
Raised Fist0
DSA Javascriptprogramming

Path Compression in Union Find in DSA Javascript

Choose your learning style10 modes available
Mental Model
Path compression makes finding the leader of a group faster by making every node on the path point directly to the leader.
Analogy: Imagine a family tree where each person points to their parent. Path compression is like updating everyone in the chain to point directly to the oldest ancestor, so future lookups are quicker.
1 -> 2 -> 3 -> 4 -> null
↑
start (find 1)

After path compression:
1 -> 4
2 -> 4
3 -> 4
4 -> null
Dry Run Walkthrough
Input: Union sets: union(1,2), union(2,3), union(3,4); then find(1)
Goal: Find the leader of element 1 and compress the path so future finds are faster
Step 1: union(1,2): link leader of 1 to leader of 2
1 -> 2 -> null
2 -> null
3 -> null
4 -> null
Why: We connect 1 and 2 so they share the same leader
Step 2: union(2,3): link leader of 2 to leader of 3
1 -> 2 -> 3 -> null
2 -> 3 -> null
3 -> null
4 -> null
Why: We connect 2 and 3, extending the chain
Step 3: union(3,4): link leader of 3 to leader of 4
1 -> 2 -> 3 -> 4 -> null
2 -> 3 -> 4 -> null
3 -> 4 -> null
4 -> null
Why: We connect 3 and 4, making 4 the leader
Step 4: find(1): traverse from 1 to leader 4
1 -> 2 -> 3 -> 4 -> null
↑
current at 1
Why: We need to find the leader of 1 by following parents
Step 5: path compression: update 1, 2, 3 to point directly to 4
1 -> 4 -> null
2 -> 4 -> null
3 -> 4 -> null
4 -> null
Why: This flattens the structure for faster future finds
Result:
1 -> 4 -> null
2 -> 4 -> null
3 -> 4 -> null
4 -> null
Leader of 1 is 4
Annotated Code
DSA Javascript
class UnionFind {
  constructor(size) {
    this.parent = Array(size + 1).fill(0).map((_, i) => i);
  }

  find(x) {
    if (this.parent[x] !== x) {
      this.parent[x] = this.find(this.parent[x]); // path compression
    }
    return this.parent[x];
  }

  union(a, b) {
    const rootA = this.find(a);
    const rootB = this.find(b);
    if (rootA !== rootB) {
      this.parent[rootA] = rootB; // link rootA to rootB
    }
  }
}

// Driver code
const uf = new UnionFind(4);
uf.union(1, 2);
uf.union(2, 3);
uf.union(3, 4);
const leader = uf.find(1);

// Print parent array to show path compression effect
let result = '';
for (let i = 1; i <= 4; i++) {
  result += `${i} -> ${uf.parent[i]}\n`;
}
console.log(result.trim());
console.log(`Leader of 1 is ${leader}`);
if (this.parent[x] !== x) { this.parent[x] = this.find(this.parent[x]); }
compress path by making x point directly to leader
const rootA = this.find(a); const rootB = this.find(b);
find leaders of both elements before union
if (rootA !== rootB) { this.parent[rootA] = rootB; }
link one leader to the other to union sets
OutputSuccess
1 -> 4 2 -> 4 3 -> 4 4 -> 4 Leader of 1 is 4
Complexity Analysis
Time: O(α(n)) per find/union operation because path compression flattens the tree making future operations almost constant time
Space: O(n) for storing the parent array for n elements
vs Alternative: Without path compression, find operations can be O(n) in worst case due to long chains; path compression reduces this to near O(1)
Edge Cases
Finding leader of an element that is its own leader
Returns the element itself immediately without recursion
DSA Javascript
if (this.parent[x] !== x)
Union of two elements already in the same set
No change to parent array, avoids unnecessary linking
DSA Javascript
if (rootA !== rootB)
Union or find on element outside range
Not handled explicitly; would cause error or incorrect behavior
DSA Javascript
No explicit guard in code
When to Use This Pattern
When you see problems about grouping elements and quickly checking if two elements belong to the same group, use Union Find with path compression to optimize repeated queries.
Common Mistakes
Mistake: Not updating the parent during find, missing path compression
Fix: Add assignment this.parent[x] = this.find(this.parent[x]) inside find to flatten the path
Mistake: Linking parents incorrectly in union causing cycles
Fix: Always link root of one set to root of another after find to avoid cycles
Summary
Path compression speeds up finding the leader by making nodes point directly to the leader.
Use it when you have many union and find operations on disjoint sets to keep queries fast.
The key insight is flattening the tree structure during find to reduce future traversal time.

Practice

(1/5)
1. What is the main purpose of path compression in the Union Find data structure?
easy
A. To speed up the find operation by flattening the tree structure
B. To merge two sets without checking their roots
C. To initialize the parent array with default values
D. To count the number of connected components

Solution

  1. Step 1: Understand the role of path compression

    Path compression is used during the find operation to make future queries faster by making nodes point directly to the root.
  2. Step 2: Identify the effect on the tree structure

    This flattens the tree, reducing the height and speeding up subsequent find calls.
  3. Final Answer:

    To speed up the find operation by flattening the tree structure -> Option A
  4. Quick Check:

    Path compression = flatten tree = faster find [OK]
Hint: Path compression flattens trees to speed up find [OK]
Common Mistakes:
  • Confusing path compression with union by rank
  • Thinking it merges sets without root checks
  • Believing it initializes data structures
2. Which of the following is the correct syntax for the find function with path compression in JavaScript?
easy
A. function find(x) { if (parent[x] === x) return x; else return find(parent[x]); }
B. function find(x) { if (parent[x] !== x) parent[x] = find(parent[x]); return parent[x]; }
C. function find(x) { while (parent[x] !== x) x = parent[x]; return x; }
D. function find(x) { parent[x] = x; return x; }

Solution

  1. Step 1: Identify path compression in the code

    function find(x) { if (parent[x] !== x) parent[x] = find(parent[x]); return parent[x]; } updates parent[x] to the root during recursion, which is path compression.
  2. 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 to parent[x]. function find(x) { parent[x] = x; return x; } resets parent incorrectly.
  3. Final Answer:

    function find(x) { if (parent[x] !== x) parent[x] = find(parent[x]); return parent[x]; } -> Option B
  4. Quick Check:

    Path compression requires parent update = function find(x) { if (parent[x] !== x) parent[x] = find(parent[x]); return parent[x]; } [OK]
Hint: Look for parent update inside find for path compression [OK]
Common Mistakes:
  • Missing parent update for path compression
  • Using iteration without compression
  • Resetting parent incorrectly
3. Given the following code snippet, what will be the output of 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);
medium
A. [0, 0, 0, 0, 4]
B. [0, 0, 1, 2, 4]
C. [0, 0, 1, 1, 4]
D. [0, 1, 1, 2, 4]

Solution

  1. 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.
  2. 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].
  3. Final Answer:

    [0, 0, 0, 0, 4] -> Option A
  4. Quick Check:

    Path compression sets parents to root = [0,0,0,0,4] [OK]
Hint: Follow recursion and update parents to root [OK]
Common Mistakes:
  • Not updating all parents during recursion
  • Confusing parent indices
  • Assuming no change after find
4. Identify the bug in the following find function implementing path compression:
function find(x) {
  if (parent[x] === x) return x;
  else find(parent[x]);
}
medium
A. Function should use iteration instead of recursion
B. Incorrect base condition for recursion
C. Parent array is not updated for path compression
D. Missing return statement in the else branch

Solution

  1. Step 1: Check the recursive calls and returns

    The else branch calls find(parent[x]) but does not return its result, so the function returns undefined for non-root nodes.
  2. Step 2: Confirm missing return causes bug

    Without returning the recursive call, the function fails to return the root, breaking the find operation.
  3. Final Answer:

    Missing return statement in the else branch -> Option D
  4. Quick Check:

    Recursive calls must return values [OK]
Hint: Always return recursive find calls [OK]
Common Mistakes:
  • Forgetting to return recursive call result
  • Misunderstanding base case
  • Thinking iteration is required
5. You have a Union Find structure with 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?
hard
A. [0, 0, 2, 2, 4]
B. [0, 0, 4, 2, 4]
C. [0, 0, 4, 4, 4]
D. [0, 0, 2, 4, 4]

Solution

  1. 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.
  2. 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.
  3. Final Answer:

    [0, 0, 4, 4, 4] -> Option C
  4. Quick Check:

    Union attaches root, find compresses path [OK]
Hint: Union attaches root; find compresses path to root [OK]
Common Mistakes:
  • Not updating parent after union
  • Ignoring path compression updates
  • Confusing rank usage
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard