Path Compression in Union Find in DSA Python - Time & Space Complexity
We want to understand how fast the "find" operation runs when we use path compression in Union Find.
Specifically, how does the time grow as we have more elements and unions?
Analyze the time complexity of the following code snippet.
class UnionFind:
def __init__(self, n):
self.parent = list(range(n))
def find(self, x):
if self.parent[x] != x:
self.parent[x] = self.find(self.parent[x]) # Path compression
return self.parent[x]
This code finds the root parent of element x and compresses the path to speed up future finds.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursive calls in
findto reach the root parent. - How many times: At most once per level of the tree from x to root, but path compression flattens this over time.
Initially, the find operation may take longer if the tree is tall, but path compression flattens the tree quickly.
| Input Size (n) | Approx. Operations per find |
|---|---|
| 10 | About 2-3 steps after some finds |
| 100 | About 4-5 steps initially, fewer after compression |
| 1000 | Starts higher but quickly reduces to very few steps |
Pattern observation: The cost per find grows very slowly and almost stays constant after many operations.
Time Complexity: O(α(n))
This means each find runs in almost constant time, where α(n) is the very slow-growing inverse Ackermann function.
[X] Wrong: "Each find always takes time proportional to the height of the tree, which can be large."
[OK] Correct: Path compression flattens the tree during finds, so the height effectively shrinks, making future finds much faster.
Understanding path compression helps you explain how Union Find achieves near-constant time operations, a key skill for efficient algorithms.
"What if we removed path compression and only used union by rank? 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 CQuick Check:
Path compression = speed up find [OK]
- Confusing path compression with union operation
- Thinking it deletes elements
- Believing it sorts elements
find function with path compression in Python?Solution
Step 1: Check for path compression in the code
def 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: Verify other options
def find(x): while parent[x] != x: x = parent[x] return x uses iteration but no path compression update. def find(x): return x if parent[x] == x else find(parent[x]) lacks assignment toparent[x]. def find(x): parent[x] = x return x incorrectly resetsparent[x]always.Final Answer:
def find(x): if parent[x] != x: parent[x] = find(parent[x]) return parent[x] -> Option DQuick Check:
Path compression requires assignment in find [OK]
- Missing assignment to parent[x]
- Using iteration without updating parents
- Resetting parent[x] incorrectly
print(parent) after the operations?parent = [0, 1, 2, 3, 4]
def find(x):
if parent[x] != x:
parent[x] = find(parent[x])
return parent[x]
def union(a, b):
rootA = find(a)
rootB = find(b)
if rootA != rootB:
parent[rootB] = rootA
union(1, 2)
union(2, 3)
find(3)
print(parent)Solution
Step 1: Perform unions and track parents
union(1,2): parent[2] = 1; union(2,3): parent[3] = find(2) = 1, so parent[3] = 1.Step 2: Apply find(3) with path compression
find(3) updates parent[3] to root 1 (already 1), so no change. Final parent array: [0,1,1,1,4]Final Answer:
[0, 1, 1, 1, 4] -> Option AQuick Check:
Parents after unions and find = [0,1,1,1,4] [OK]
- Not updating parent during find
- Confusing root assignments
- Ignoring path compression effect
find function that is supposed to implement path compression:def find(x):
if parent[x] == x:
return x
else:
find(parent[x])Solution
Step 1: Check the else branch
The else branch callsfind(parent[x])but does not return its result, so the function returns None.Step 2: Understand path compression requirement
Without returning the recursive call result, path compression and correct root finding fail.Final Answer:
Missing return statement in the else branch -> Option BQuick Check:
Return recursive find result [OK]
- Forgetting return in recursion
- Misunderstanding base case
- Assuming iteration is required
union(0,1), union(1,2), and union(3,4), you call find(2) and find(4) with path compression. Which of the following statements is true about the parent array after these operations?Solution
Step 1: Analyze unions
union(0,1) and union(1,2) merge 0,1,2 into one set. union(3,4) merges 3 and 4 into another set.Step 2: Effect of find with path compression
find(2) compresses path so 2 points directly to root of set {0,1,2}. find(4) compresses path so 4 points directly to root of set {3,4}.Step 3: Confirm roots and parent array
Sets remain separate; 0,1,2 share root; 3,4 share root; path compression flattens trees.Final Answer:
Elements 0, 1, and 2 will have the same root, and 3 and 4 will have the same root, with path compression applied -> Option AQuick Check:
Unions merge sets; path compression flattens but does not merge sets [OK]
- Thinking path compression merges sets
- Assuming all elements share one root
- Confusing union and find roles
Ready to prove it?
Pass the test and this pattern moves unknown
