其实还是用并查集将 独立的岛屿视为独立的子集。
count其实是集合的个数,同一个块岛屿被压缩成了一个集合,而每个表示海洋的格子依然被看作独立的集合,在所有的格子都走完一遍后,count = 被压缩的岛屿 + 所有表示海洋的独立格子的数目,因此减去格子的数目比较重要。
class Solution {
private int rows;
private int cols;
public int numIslands(char[][] grid) {
rows = grid.length;
if (rows == 0) {
return 0;
}
cols = grid[0].length;
//空地的数量
int spaces = 0;
UnionFind unionFind = new UnionFind(cols * rows);
int[][] directions = {{1, 0}, {0, 1}};
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (grid[i][j] == '0') {
spaces++;
} else {
for (int[] direction : directions) {
int newX = i + direction[0];
int newY = j + direction[1];
if (newX < rows && newY < cols && grid[newX][newY] == '1') {
unionFind.union(getIndex(i, j), getIndex(newX, newY));
}
}
}
}
}
//没懂为什么要减去spaces
return unionFind.getCount() - spaces;
}
private int getIndex(int i, int j) {
return i * cols + j;
}
private class UnionFind{
private int count;
private int[] parent;
public int getCount() {
return count;
}
public UnionFind(int n) {
this.count = n;
parent = new int[n];
for (int i = 0; i < n; i++) {
parent[i] = i;
}
}
private int find(int x) {
while (x != parent[x]) {
parent[x] = parent[parent[x]];
x = parent[x];
}
return x;
}
public void union(int x, int y) {
int xRoot = find(x);
int yRoot = find(y);
if (xRoot == yRoot) {
return;
}
parent[xRoot] = yRoot;
count--;
}
}
}