Bird
Raised Fist0
DSA Pythonprogramming~15 mins

Union Find Disjoint Set Data Structure in DSA Python - Deep Dive

Choose your learning style10 modes available
Overview - Union Find Disjoint Set Data Structure
What is it?
Union Find Disjoint Set is a way to keep track of groups of items that are connected or related. It helps quickly find out if two items are in the same group and to join two groups into one. Imagine having many separate sets and wanting to combine or check them efficiently. This data structure makes these operations fast and simple.
Why it matters
Without Union Find, checking if items belong to the same group or merging groups would be slow and complicated, especially when there are many items. This would make problems like network connectivity, social groups, or clustering much harder to solve quickly. Union Find helps computers solve these problems efficiently, saving time and resources.
Where it fits
Before learning Union Find, you should understand basic data structures like arrays and sets. After this, you can explore graph algorithms like Kruskal's Minimum Spanning Tree or connected components, which use Union Find to work efficiently.
Mental Model
Core Idea
Union Find keeps track of which items belong together by linking them in groups and quickly finding the group's representative.
Think of it like...
Think of Union Find like a classroom where students form friend circles. Each circle has a leader, and if two circles become friends, their leaders agree to merge the circles under one leader. To check if two students are friends, you just check if they share the same leader.
Sets and leaders:

  [1]     [2]     [3]     [4]
   |       |       |       |
  (1)     (2)     (3)     (4)  <- each number is its own leader

After union(1, 2):

  [1]---[2]   [3]   [4]
   |      |    |     |
  (1)    (1)  (3)   (4)  <- 1 is leader of 1 and 2

After union(3, 4):

  [1]---[2]   [3]---[4]
   |      |    |      |
  (1)    (1)  (3)    (3)  <- 3 is leader of 3 and 4

After union(2, 3):

  [1]---[2]---[3]---[4]
   |       |      |     |
  (1)     (1)    (1)   (1)  <- all share leader 1
Build-Up - 7 Steps
1
FoundationUnderstanding Disjoint Sets
🤔
Concept: Learn what disjoint sets are: groups with no overlap.
Disjoint sets are collections of items where no item appears in more than one group. For example, if you have sets {1,2} and {3,4}, these sets are disjoint because they share no common items. Union Find helps manage these sets efficiently.
Result
You understand that disjoint sets are separate groups with no shared elements.
Knowing what disjoint sets are is essential because Union Find manages these groups and their connections.
2
FoundationBasic Operations: Find and Union
🤔
Concept: Introduce the two main operations: finding a group's leader and merging groups.
Find operation returns the leader (representative) of the group an item belongs to. Union operation merges two groups by connecting their leaders. For example, if 1's leader is 1 and 2's leader is 2, union(1,2) makes one leader for both.
Result
You can identify which group an item belongs to and combine two groups into one.
Understanding these operations is key because they form the foundation of how Union Find works.
3
IntermediateImplementing Union Find with Parent Array
🤔Before reading on: do you think each item stores its group's leader directly or indirectly? Commit to your answer.
Concept: Use an array where each item points to its parent, forming trees representing groups.
We keep an array called 'parent' where parent[i] is the parent of item i. Initially, each item is its own parent (leader). To find the leader, we follow parents until we reach an item that is its own parent. To union two items, we set one leader's parent to the other leader.
Result
You have a simple tree structure where each group's leader is the root node.
Knowing that groups form trees helps understand how find and union work by traversing and linking these trees.
4
IntermediatePath Compression Optimization
🤔Before reading on: do you think find operation always takes the same time or can it be improved? Commit to your answer.
Concept: Improve find by making nodes point directly to the leader to speed up future finds.
Path compression means when you find the leader of an item, you update all nodes along the path to point directly to the leader. This flattens the tree and makes future find operations faster.
Result
Find operations become almost constant time after some unions and finds.
Understanding path compression reveals why Union Find is so efficient in practice.
5
IntermediateUnion by Rank or Size
🤔Before reading on: do you think always attaching one tree to another arbitrarily is efficient? Commit to your answer.
Concept: Attach smaller trees under bigger trees to keep trees shallow.
Union by rank or size means when merging two groups, attach the smaller tree under the bigger tree's leader. This keeps the tree height low, improving find operation speed.
Result
Trees remain balanced, preventing long chains and slow finds.
Knowing how to keep trees balanced is crucial for maintaining Union Find's efficiency.
6
AdvancedFull Python Implementation with Optimizations
🤔Before reading on: do you think combining path compression and union by rank is necessary or optional? Commit to your answer.
Concept: Combine path compression and union by rank for near-constant time operations.
Here is a complete Python class: class UnionFind: def __init__(self, n): self.parent = list(range(n)) self.rank = [0] * n def find(self, x): if self.parent[x] != x: self.parent[x] = self.find(self.parent[x]) # path compression return self.parent[x] def union(self, x, y): rootX = self.find(x) rootY = self.find(y) if rootX != rootY: if self.rank[rootX] < self.rank[rootY]: self.parent[rootX] = rootY elif self.rank[rootX] > self.rank[rootY]: self.parent[rootY] = rootX else: self.parent[rootY] = rootX self.rank[rootX] += 1 uf = UnionFind(5) uf.union(0, 1) uf.union(1, 2) uf.union(3, 4) print([uf.find(i) for i in range(5)]) Output: [0, 0, 0, 3, 3]
Result
[0, 0, 0, 3, 3]
Understanding this full implementation shows how the two optimizations work together to keep operations very fast.
7
ExpertAmortized Analysis and Practical Limits
🤔Before reading on: do you think each find or union always takes constant time? Commit to your answer.
Concept: Operations are almost constant time on average, but worst-case can be higher; amortized analysis explains this.
Though find and union can take longer in some cases, the average time over many operations is almost constant, called inverse Ackermann function time, which grows extremely slowly. This means Union Find is practically very fast even for huge data.
Result
You understand why Union Find is efficient in real-world large problems.
Knowing amortized complexity explains why Union Find is preferred in performance-critical applications.
Under the Hood
Union Find works by representing groups as trees where each node points to a parent. The root node is the group's leader. Find operation climbs up the tree to find the root. Union operation links roots to merge groups. Path compression flattens trees by making nodes point directly to roots during find. Union by rank keeps trees balanced by attaching smaller trees under larger ones.
Why designed this way?
This design balances simplicity and speed. Early methods used simple arrays but were slow. Trees allow flexible grouping. Path compression and union by rank were introduced to avoid deep trees and slow searches, making operations almost constant time. Alternatives like linked lists or hash sets are slower for union/find operations.
Union Find internal structure:

  item -> parent

  0 -> 0 (root)
  1 -> 0
  2 -> 0
  3 -> 3 (root)
  4 -> 3

Find(2): 2 -> 0 (root)
Union(1,3): attach root of 3 under root of 0

After union:

  0 -> 0 (root)
  1 -> 0
  2 -> 0
  3 -> 0
  4 -> 3

Path compression updates 4's parent to 0 when find(4) is called.
Myth Busters - 4 Common Misconceptions
Quick: Does union operation always merge the smaller group into the bigger one? Commit yes or no.
Common Belief:Union always attaches the smaller group under the bigger group automatically.
Tap to reveal reality
Reality:Union only attaches smaller under bigger if union by size or rank is implemented. Without it, union may attach arbitrarily, causing slow operations.
Why it matters:Ignoring union by size/rank can lead to tall trees and slow find operations, hurting performance.
Quick: Does find operation always return the immediate parent of an item? Commit yes or no.
Common Belief:Find returns the direct parent of an item, not necessarily the group's leader.
Tap to reveal reality
Reality:Find returns the root leader by following parents up the tree, not just the immediate parent.
Why it matters:Misunderstanding find can cause incorrect group checks and bugs in algorithms relying on correct group leaders.
Quick: Is Union Find suitable for dynamic removal of items from groups? Commit yes or no.
Common Belief:Union Find supports removing items from groups easily.
Tap to reveal reality
Reality:Union Find does not support efficient removal of items from groups; it only supports union and find operations.
Why it matters:Trying to remove items using Union Find leads to incorrect results or complex workarounds.
Quick: Does path compression change the group membership of items? Commit yes or no.
Common Belief:Path compression can change which group an item belongs to.
Tap to reveal reality
Reality:Path compression only changes the internal parent pointers to speed up find; it does not change group membership.
Why it matters:Confusing path compression with group changes can lead to wrong assumptions about data structure behavior.
Expert Zone
1
Union Find's efficiency depends heavily on combining path compression with union by rank; using only one optimization reduces performance gains.
2
The inverse Ackermann function time complexity is so slow-growing that for all practical input sizes, Union Find operations are effectively constant time.
3
In some applications, storing extra information per group (like size or sum) requires careful updates during union to maintain correctness.
When NOT to use
Union Find is not suitable when you need to remove items from groups or when group membership changes frequently in complex ways. For such cases, use dynamic connectivity data structures like Link-Cut Trees or Euler Tour Trees.
Production Patterns
Union Find is widely used in network connectivity checks, Kruskal's algorithm for minimum spanning trees, image processing for connected components, and clustering algorithms. It is also used in social network analysis to find friend groups and in database systems for equivalence queries.
Connections
Graph Theory
Union Find is used to find connected components and cycles in graphs.
Understanding Union Find helps grasp how graph connectivity is efficiently managed without exploring all edges repeatedly.
Equivalence Relations in Mathematics
Union Find models equivalence classes by grouping elements that are equivalent under a relation.
Knowing equivalence relations clarifies why Union Find groups items and how it ensures each group is a distinct class.
Social Network Analysis
Union Find models friend groups or communities by merging connected individuals.
Seeing Union Find as managing social groups helps understand its practical use in clustering and community detection.
Common Pitfalls
#1Not using path compression causes slow find operations.
Wrong approach:def find(x): while parent[x] != x: x = parent[x] return x
Correct approach:def find(x): if parent[x] != x: parent[x] = find(parent[x]) return parent[x]
Root cause:Without path compression, trees can become tall, making find operations slow.
#2Union without rank causes unbalanced trees.
Wrong approach:def union(x, y): parent[find(x)] = find(y)
Correct approach:def union(x, y): rootX = find(x) rootY = find(y) if rank[rootX] < rank[rootY]: parent[rootX] = rootY elif rank[rootX] > rank[rootY]: parent[rootY] = rootX else: parent[rootY] = rootX rank[rootX] += 1
Root cause:Ignoring rank leads to deep trees and slow operations.
#3Assuming Union Find supports item removal.
Wrong approach:# Trying to remove item 2 from its group parent[2] = 2 # Incorrect manual reset
Correct approach:# Union Find does not support removal; use other data structures
Root cause:Union Find is designed only for union and find; removal breaks its assumptions.
Key Takeaways
Union Find Disjoint Set efficiently manages groups by linking items in trees with leaders.
The two main operations are find (to get group leader) and union (to merge groups).
Path compression and union by rank keep the structure flat and operations fast.
Union Find is essential for problems involving connectivity and grouping in graphs and networks.
It does not support removing items from groups and is best used when groups only merge or are queried.

Practice

(1/5)
1. What is the main purpose of the Union Find Disjoint Set data structure?
easy
A. To efficiently track and merge groups of connected elements
B. To sort elements in ascending order
C. To store key-value pairs for fast lookup
D. To implement a queue with fast enqueue and dequeue

Solution

  1. Step 1: Understand the purpose of Union Find

    The Union Find data structure is designed to keep track of which elements belong to which groups or sets, especially when these groups merge.
  2. Step 2: Compare with other data structures

    Sorting, key-value storage, and queue operations are unrelated to Union Find's main goal.
  3. Final Answer:

    To efficiently track and merge groups of connected elements -> Option A
  4. Quick Check:

    Union Find = track and merge groups [OK]
Hint: Union Find = manage connected groups fast [OK]
Common Mistakes:
  • Confusing Union Find with sorting algorithms
  • Thinking it stores key-value pairs
  • Mixing it up with queue or stack data structures
2. Which of the following is the correct way to initialize a Union Find parent array for 5 elements in Python?
easy
A. parent = [None] * 5
B. parent = [1, 1, 1, 1, 1]
C. parent = [5, 5, 5, 5, 5]
D. parent = [0, 1, 2, 3, 4]

Solution

  1. Step 1: Understand initialization of Union Find

    Each element starts as its own parent, so the parent array should have each index equal to itself.
  2. Step 2: Check each option

    parent = [0, 1, 2, 3, 4] correctly sets parent[i] = i for i in 0 to 4. Others do not represent this.
  3. Final Answer:

    parent = [0, 1, 2, 3, 4] -> Option D
  4. Quick Check:

    Parent array init = self indices [OK]
Hint: Parent array starts with self indices [OK]
Common Mistakes:
  • Setting all parents to 1 or a fixed number
  • Using None which breaks find operations
  • Confusing size array with parent array
3. What is the output of the following code?
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])
        return self.parent[x]
    def union(self, a, b):
        rootA = self.find(a)
        rootB = self.find(b)
        if rootA != rootB:
            self.parent[rootB] = rootA

uf = UnionFind(4)
uf.union(0, 1)
uf.union(2, 3)
uf.union(1, 3)
print(uf.parent)
medium
A. [0, 0, 0, 2]
B. [0, 0, 0, 0]
C. [0, 0, 2, 2]
D. [0, 1, 2, 3]

Solution

  1. Step 1: Trace unions step-by-step

    Init: [0,1,2,3]
    Union(0,1): find(0)=0, find(1)=1 -> parent[1]=0 -> [0,0,2,3]
    Union(2,3): find(2)=2, find(3)=3 -> parent[3]=2 -> [0,0,2,2]
    Union(1,3): find(1)=0, find(3)=2 (sets parent[3]=2) -> parent[2]=0 -> [0,0,0,2]
  2. Step 2: Verify print output

    No additional find calls before print. parent[3] points to 2 (now root 0), but not fully compressed to 0. Output: [0, 0, 0, 2]
  3. Final Answer:

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

    parent = [0,0,0,2] after partial compression [OK]
Hint: Trace find calls and compression timing during union [OK]
Common Mistakes:
  • Forgetting last union sets parent[2]=0 -> [0,0,2,2]
  • Over-applying path compression -> [0,0,0,0]
  • Ignoring unions entirely
4. Identify the bug in this Union Find union method:
def union(self, a, b):
    rootA = self.find(a)
    rootB = self.find(b)
    if rootA != rootB:
        self.parent[rootA] = rootB
medium
A. The find method is not called correctly
B. It should assign parent of rootB to rootA, not the other way
C. The if condition should be rootA == rootB
D. The method is missing a return statement

Solution

  1. Step 1: Understand union direction

    Union should attach one root to the other to merge sets. Usually, parent of rootB is set to rootA or vice versa consistently.
  2. Step 2: Check given code

    Code sets parent[rootA] = rootB, which reverses the usual convention and can cause incorrect tree structure or confusion.
  3. Final Answer:

    It should assign parent of rootB to rootA, not the other way -> Option B
  4. Quick Check:

    Union sets parent[rootB] = rootA [OK]
Hint: Union sets parent of second root to first root [OK]
Common Mistakes:
  • Swapping roots incorrectly in union
  • Not calling find before union
  • Confusing equality check in if condition
5. Given a graph with 6 nodes and edges [(0,1), (1,2), (3,4)], how many connected components does the Union Find structure report after union operations on these edges?
hard
A. 4
B. 2
C. 3
D. 5

Solution

  1. Step 1: Initialize 6 separate nodes

    Initially, each node is its own component: 6 components total.
  2. Step 2: Perform unions for edges

    Union(0,1) merges nodes 0 and 1 -> components reduce to 5.
    Union(1,2) merges node 2 with 0-1 group -> components reduce to 4.
    Union(3,4) merges nodes 3 and 4 -> components reduce to 3.
  3. Step 3: Count remaining components

    Node 5 remains alone -> total components = 3.
  4. Final Answer:

    3 -> Option C
  5. Quick Check:

    6 nodes - 3 unions = 3 components [OK]
Hint: Components = nodes - unions done [OK]
Common Mistakes:
  • Counting edges instead of components
  • Forgetting isolated nodes count as components
  • Miscounting after unions
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