Skip to content

Commit 898c8e9

Browse files
committed
Refactor the code by introducing the UnionFind class
1 parent cade61f commit 898c8e9

File tree

2 files changed

+86
-69
lines changed

2 files changed

+86
-69
lines changed
Lines changed: 8 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,23 @@
11
package org.sean.array;
22

3+
import org.sean.graph.UnionFind;
4+
35
/***
46
* 200. Number of Islands
57
*/
68
public class IslandCounter {
7-
private int[] parent; // parent[i] = parent of i
8-
private int[] size; // size[i] = number of sites in subtree rooted at i
9-
private int count; // number of components
10-
11-
private void init(int n) {
12-
count = n;
13-
parent = new int[n];
14-
size = new int[n];
15-
for (int i = 0; i < n; i++) {
16-
parent[i] = i;
17-
size[i] = 1;
18-
}
19-
}
20-
21-
/**
22-
* The number of components.
23-
*/
24-
private int count() {
25-
return count;
26-
}
27-
28-
private int find(int p) {
29-
validate(p);
30-
while (p != parent[p])
31-
p = parent[p];
32-
return p;
33-
}
34-
35-
// validate that p is a valid index
36-
private void validate(int p) {
37-
int n = parent.length;
38-
if (p < 0 || p >= n) {
39-
throw new IllegalArgumentException("index " + p + " is not between 0 and " + (n - 1));
40-
}
41-
}
42-
43-
private boolean connected(int p, int q) {
44-
return find(p) == find(q);
45-
}
46-
47-
private void union(int p, int q) {
48-
int rootP = find(p);
49-
int rootQ = find(q);
50-
if (rootP == rootQ) return;
51-
52-
// make smaller root point to larger one
53-
if (size[rootP] < size[rootQ]) {
54-
parent[rootP] = rootQ;
55-
size[rootQ] += size[rootP];
56-
} else {
57-
parent[rootQ] = rootP;
58-
size[rootP] += size[rootQ];
59-
}
60-
count--;
61-
}
62-
63-
private void link(int p, int q) {
64-
if (!connected(p, q)) {
65-
union(p, q);
66-
}
67-
}
9+
private UnionFind unionFind;
6810

6911
public int numIslands(char[][] grid) {
70-
if (grid == null || grid.length == 0)
71-
return 0;
12+
if (grid == null || grid.length == 0) return 0;
7213
int row = grid.length;
7314
int col = grid[0].length;
7415

7516
int n = row * col;
7617
int p = -1;
7718
int q = -1;
7819

79-
// take advantage of WeightedQuickUnionUF from Algs4
80-
// https://algs4.cs.princeton.edu/15uf/WeightedQuickUnionUF.java.html
81-
init(n);
20+
unionFind = new UnionFind(n);
8221

8322
int zeroCnt = 0;
8423

@@ -90,15 +29,15 @@ public int numIslands(char[][] grid) {
9029
if (i + 1 < row) {
9130
if (grid[i + 1][j] == '1') {
9231
int p2 = (i + 1) * col + j;
93-
link(pos, p2);
32+
unionFind.union(pos, p2);
9433

9534
System.out.println(String.format(">>> Evaluate pos [%d, %d]", pos, p2));
9635
}
9736
}
9837
if (j + 1 < col) {
9938
if (grid[i][j + 1] == '1') {
10039
int p2 = i * col + j + 1;
101-
link(pos, p2);
40+
unionFind.union(pos, p2);
10241

10342
System.out.println(String.format(">>> Evaluate pos [%d, %d]", pos, p2));
10443
}
@@ -109,6 +48,6 @@ public int numIslands(char[][] grid) {
10948
}
11049
}
11150

112-
return count() - zeroCnt;
51+
return unionFind.count() - zeroCnt;
11352
}
11453
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package org.sean.graph;
2+
3+
import java.util.Arrays;
4+
import java.util.LinkedList;
5+
import java.util.List;
6+
7+
// Case Study: Union-Find
8+
// https://algs4.cs.princeton.edu/15uf/
9+
public class UnionFind {
10+
private int components;
11+
private final int[] parents;
12+
private final int[] sz;
13+
14+
public UnionFind(int n) {
15+
components = n;
16+
17+
parents = new int[n];
18+
for (int i = 0; i < n; i++) {
19+
parents[i] = i; // self
20+
}
21+
22+
sz = new int[n];
23+
Arrays.fill(sz, 1);
24+
}
25+
26+
private int topParent(int p) {
27+
int curr = p;
28+
while (parents[curr] != curr) {
29+
curr = parents[curr];
30+
}
31+
return curr;
32+
}
33+
34+
public void union(int p, int q) {
35+
int pt1 = topParent(p);
36+
int pt2 = topParent(q);
37+
if (pt1 != pt2) {
38+
// weighted quick union:
39+
// connect the smaller tree to the larger
40+
if (sz[pt1] > sz[pt2]) {
41+
parents[pt2] = pt1;
42+
sz[pt1] += sz[pt2];
43+
} else {
44+
parents[pt1] = pt2;
45+
sz[pt2] += sz[pt1];
46+
}
47+
48+
--components;
49+
}
50+
}
51+
52+
public boolean isConnected(int p, int q) {
53+
return topParent(p) == topParent(q);
54+
}
55+
56+
public int count() {
57+
return components;
58+
}
59+
60+
public static void main(String[] args) {
61+
List<int[]> arr = new LinkedList<>();
62+
arr.add(new int[] {4, 3});
63+
arr.add(new int[] {3, 8});
64+
arr.add(new int[] {6, 5});
65+
arr.add(new int[] {9, 4});
66+
arr.add(new int[] {2, 1});
67+
arr.add(new int[] {5, 0});
68+
arr.add(new int[] {7, 2});
69+
arr.add(new int[] {6, 1});
70+
71+
UnionFind unionFind = new UnionFind(10);
72+
for (int[] pair : arr) {
73+
unionFind.union(pair[0], pair[1]);
74+
}
75+
76+
System.out.println("Components : " + unionFind.count());
77+
}
78+
}

0 commit comments

Comments
 (0)