Disjoint sets are sets whose intersection is the empty set. For example, {0, 1, 2} and {3} are disjoint sets, while {0, 1, 2} and {2, 3} are not
Problem
Given some separated elements grouped in disjoint sets. Find
whether 2 elements in the same set or not.
Approach
How to determine if 2 elements are in the same set? Check if they have the same root/representative.
How to determine the root/representative of a set? Unionizing 2 elements by a bigger index or by a higher rank.
Implementation
Find
with compress path andUnion
by bigger index
public class DisjoinSetUnionByBiggestIndex {
int[] parents;
int N;
DisjoinSetUnionByBiggestIndex(int N) {
this.N = N;
parents = new int[N];
initDisjoinSet();
}
void initDisjoinSet() {
for (int i = 0; i < N; i++) {
parents[i] = i;
}
}
int findRoot(int x) {
if (parents[x] != x) {
parents[x] = findRoot(parents[x]);
}
return parents[x];
}
void union(int x, int y) {
int rootOfX = findRoot(x);
int rootOfY = findRoot(y);
if (rootOfX == rootOfY) {
return;
}
parents[rootOfX] = rootOfY;
}
public static void main(String[] args) {
int N = 4;
DisjoinSetUnionByBiggestIndex disjoinSet = new DisjoinSetUnionByBiggestIndex(N);
disjoinSet.union(0, 1);
disjoinSet.union(1, 2);
// Check if 1 is in the same set with 2
if (disjoinSet.findRoot(1) == disjoinSet.findRoot(2)) {
System.out.println("1 is in the same set with 2");
} else {
System.out.println("1 is not in the same set with 2");
}
// Check if 1 is in the same set with 3
if (disjoinSet.findRoot(1) == disjoinSet.findRoot(3)) {
System.out.println("1 is in the same set with 3");
} else {
System.out.println("1 is not in the same set with 3");
}
}
}
Initial state of parents
Final state of parents
after all unionizing
Find
with compress path andUnion
by higher rank
public class DisjoinSetUnionByRank {
int[] parents, ranks;
int N;
DisjoinSetUnionByRank(int N) {
this.N = N;
parents = new int[N];
ranks = new int[N];
initDisjoinSet();
}
void initDisjoinSet() {
for (int i = 0; i < N; i++) {
parents[i] = i;
}
}
int findRoot(int x) {
if (parents[x] != x) {
parents[x] = findRoot(parents[x]);
}
return parents[x];
}
void union(int x, int y) {
int rootOfX = findRoot(x);
int rootOfY = findRoot(y);
if (rootOfX == rootOfY) {
return;
}
if (ranks[rootOfX] < ranks[rootOfY]) {
parents[rootOfX] = rootOfY;
} else if (ranks[rootOfX] > ranks[rootOfY]) {
parents[rootOfY] = rootOfX;
} else {
parents[rootOfX] = rootOfY;
ranks[rootOfY] = ranks[rootOfY] + 1;
}
}
public static void main(String[] args) {
int N = 4;
DisjoinSetUnionByRank disjoinSet = new DisjoinSetUnionByRank(N);
disjoinSet.union(0, 1);
disjoinSet.union(1, 2);
// Check if 1 is in the same set with 2
if (disjoinSet.findRoot(1) == disjoinSet.findRoot(2)) {
System.out.println("1 is in the same set with 2");
} else {
System.out.println("1 is not in the same set with 2");
}
// Check if 1 is in the same set with 3
if (disjoinSet.findRoot(1) == disjoinSet.findRoot(3)) {
System.out.println("1 is in the same set with 3");
} else {
System.out.println("1 is not in the same set with 3");
}
}
}
Initial state of parents
Final state of parents
after all unionizing