Disjoint Set: Any two sets have no common elements. There are three different implementations:
1. Union-By-Height: When performing union on two root nodes, merge the root node with the smaller height onto the root node with the higher height
2. Union-By-Size: When performing union on two root nodes, merge the root node with smaller size onto the root node with bigger size
3. Union-By-Rank: Union is the same as Union-By-Height. When performing Find, it makes every node on the path points to its root node.
API explanation:
1. Initialize Disjoint Set: Initialize the disjoint set with size n - O(n)
2. Union: Merge two disjoint sets - O(1)
3. Find: Find the root node id given an id - O(log(n)) with Union-By-Height and Union-By-Size and O(α(n)) with Union-By-Rank with path compression