305. Number of Islands II (union-find)
naive
BFS in leetcode 200, each cell call BFS one time
T: O(mn*mn)
S: O(mn)
union find
T: O(mn)
S: O(mn)
class Solution {
private int[][] dirs = {{1,0},{0,1},{-1,0},{0,-1}};
public List<Integer> numIslands2(int m, int n, int[][] positions) {
List<Integer> res = new ArrayList<>();
if (positions == null || positions.length == 0) {
return res;
}
UnionFind uf = new UnionFind();
boolean[][] isLand = new boolean[m][n];
for (int[] position : positions) {
int x = position[0];
int y = position[1];
if (isLand[x][y]) {
res.add(uf.getNumOfSet());
continue;
}
isLand[x][y] = true;
uf.add(toId(x, y, n));
for (int[] dir : dirs) {
int neighborX = x + dir[0];
int neighborY = y + dir[1];
if (!isValid(neighborX, neighborY, m, n, isLand)) {
continue;
}
uf.union(toId(x, y, n), toId(neighborX, neighborY, n));
}
res.add(uf.getNumOfSet());
}
return res;
}
/*
m = 4, n = 9 (4 row, 9 col)
0 1 2 3 4 5 6 7 8
9 10 11 12 => (1,2) => 1*9 + 2 = 11, x*n + y
*/
private int toId(int x, int y, int n) {
return x*n + y;
}
private boolean isValid(int x, int y, int m, int n, boolean[][] isLand) {
return x >= 0 && x < m && y >= 0 && y < n && isLand[x][y];
}
}
class UnionFind {
private Map<Integer, Integer> parent;
private Map<Integer, Integer> sizeOfSet;
private int numOfSet = 0;
UnionFind() {
this.parent = new HashMap<>();
this.sizeOfSet = new HashMap<>();
}
public void add(int x) {
if (parent.containsKey(x)) {
return;
}
parent.put(x, null);
sizeOfSet.put(x, 1);
numOfSet++;
}
public int find(int x) {
int root = x;
while (parent.get(root) != null) {
root = parent.get(root);
}
while (x != root) {
int xParent = parent.get(x);
parent.put(x, root);
x = xParent;
}
return root;
}
public void union(int x, int y) {
int rootX = find(x);
int rootY = find(y);
if (rootX != rootY) {
parent.put(rootX, rootY);
numOfSet--;
sizeOfSet.put(rootY, sizeOfSet.get(rootX)+sizeOfSet.get(rootY));
}
}
public boolean isConnected(int x, int y) {
return find(x) == find(y);
}
public int getNumOfSet() {
return numOfSet;
}
public int getSizeOfSet(int x) {
if (!sizeOfSet.containsKey(x)) {
return 0;
}
return sizeOfSet.get(find(x));
}
}new version
final version - simpler union find
T: O(mn)
S: O(mn)
Last updated
Was this helpful?