Path Compression in Union Find in DSA C++ - 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 the number of elements increases?
Analyze the time complexity of the following code snippet.
int find(int x, vector<int>& parent) {
if (parent[x] != x) {
parent[x] = find(parent[x], parent); // Path compression
}
return 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 to find until the root parent is found.
- How many times: At most, the depth of the tree before compression.
Initially, trees can be tall, so find might take several steps. But path compression flattens trees over time.
| Input Size (n) | Approx. Operations per find |
|---|---|
| 10 | About 2-3 steps on average |
| 100 | About 4-5 steps on average |
| 1000 | About 5-6 steps on average |
Pattern observation: The number of steps grows very slowly, almost constant, even as n grows large.
Time Complexity: O(α(n))
This means each find operation runs in almost constant time, where α(n) is the very slow-growing inverse Ackermann function.
[X] Wrong: "Path compression makes find run in constant time always."
[OK] Correct: While path compression greatly speeds up find, the time depends on α(n), which grows so slowly it looks constant but is not exactly constant.
Understanding path compression's time complexity shows you how smart tweaks make algorithms very efficient in practice.
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 find operation
Thefindoperation locates the root parent of a node in Union Find.Step 2: Role of path compression
Path compression updates nodes along the path to point directly to the root, reducing future search time.Final Answer:
To speed up thefindoperation by making nodes point directly to the root -> Option BQuick Check:
Path compression optimizes find = To speed up thefindoperation by making nodes point directly to the root [OK]
- Confusing path compression with union by size/rank
- Thinking it merges sets instead of optimizing find
- Assuming it initializes data structures
find function with path compression in C++?Solution
Step 1: Identify path compression usage
Path compression updatesparent[x]during recursion to root.Step 2: Check each option
int find(int x) { if(parent[x] != x) parent[x] = find(parent[x]); return parent[x]; } updatesparent[x]with recursive call result, implementing path compression correctly.Final Answer:
int find(int x) { if(parent[x] != x) parent[x] = find(parent[x]); return parent[x]; } -> Option AQuick Check:
Path compression requires assignment in recursion = int find(int x) { if(parent[x] != x) parent[x] = find(parent[x]); return parent[x]; } [OK]
- Missing assignment to parent[x] for compression
- Using iterative find without compression
- Returning parent[x] without recursion
int parent[5] = {0, 1, 2, 3, 4};
int find(int x) {
if(parent[x] != x) parent[x] = find(parent[x]);
return parent[x];
}
void unionSet(int a, int b) {
int rootA = find(a);
int rootB = find(b);
if(rootA != rootB) parent[rootB] = rootA;
}
unionSet(1, 2);
unionSet(2, 3);
find(3);
What is the state of the parent array after these operations?Solution
Step 1: Perform unions
unionSet(1,2): parent[2] = 1; unionSet(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. parent array: [0,1,1,1,4]Final Answer:
[0, 1, 1, 1, 4] -> Option DQuick Check:
Parents after unions and compression = [0,1,1,1,4] [OK]
- Not updating parent of 3 during union
- Ignoring path compression effect in find
- Confusing indices and values in parent array
find function is intended to implement path compression but has a bug:
int find(int x) {
if(parent[x] == x) return x;
find(parent[x]);
return parent[x];
}
What is the bug in this code?Solution
Step 1: Analyze recursion call
The recursive callfind(parent[x])is made but its result is not assigned back toparent[x].Step 2: Effect on path compression
Without assignment,parent[x]remains unchanged, so path compression does not happen.Final Answer:
It does not updateparent[x]during recursion for compression -> Option AQuick Check:
Missing assignment breaks path compression = It does not updateparent[x]during recursion for compression [OK]
- Thinking base case condition is wrong
- Assuming return value is incorrect
- Believing it causes infinite recursion
unionSet(0, 1); unionSet(1, 2); unionSet(3, 4); unionSet(4, 5); find(2); find(5); unionSet(2, 5); find(5);After all operations, what is the parent array state assuming path compression is used in
find?Solution
Step 1: Perform initial unions
unionSet(0,1): parent[1]=0; unionSet(1,2): parent[2]=find(1)=0; unionSet(3,4): parent[4]=3; unionSet(4,5): parent[5]=find(4)=3;Step 2: Apply finds with path compression
find(2): compresses path for 2 to 0 (already 0); find(5): compresses path for 5 to 3 (already 3); unionSet(2,5): parent[3]=find(2)=0; find(5): compresses path for 5 to 0, so parent[5]=0;Step 3: Final parent array
parent[0]=0, parent[1]=0, parent[2]=0, parent[3]=0 (updated), parent[4]=3, parent[5]=0 (compressed)Final Answer:
[0, 0, 0, 0, 3, 0] -> Option CQuick Check:
After unions and compression, parent array = [0, 0, 0, 0, 3, 0] [OK]
- Not updating parent of 3 during unionSet(2,5)
- Ignoring path compression effect on 5 after last find
- Mixing parent indices and values
Ready to prove it?
Pass the test and this pattern moves unknown
