岛屿数量
题解
可以直接深度优先或者广度优先遍历,然后统计连通图的个数。
今天用新学的并查集来做。
并查集主要用来 集合的合并和查询。
并查集的实质
- 构造关系,保存父亲节点的树结构。
- 合并集合,合并两棵树,将树的根节点并入另一个树的根节点
具体代码实现如下
int fa[305*305]; // 定义父亲节点
int siz[305*305]; // 以该节点为首的集合的元素个数
void merge(int x, int y) { // 合并两个点 x,y, 找到两个的父亲节点并合并,同时更新该集合的元素个数
//printf("(%d,%d) ", x,y);
int fx = find(x);
int fy = find(y);
if (fx==fy) return;
siz[fx] += siz[fy];
fa[fy]=fx;
}
int find(int x) { // 找到该节点的根节点
if (x == fa[x]) return x;
fa[x] = find(fa[x]);
return fa[x];
}
//初始化
for (int i=0; i<=n*m; i++) siz[i]=1, fa[i]=i;
代码
class Solution {
private:
int K = 305;
int fa[305*305];
int siz[305*305];
int dir[4][2] = {-1,0, 1,0, 0,-1, 0,1};
void merge(int x, int y) {
//printf("(%d,%d) ", x,y);
int fx = find(x);
int fy = find(y);
if (fx==fy) return;
siz[fx] += siz[fy];
fa[fy]=fx;
}
int find(int x) {
if (x == fa[x]) return x;
fa[x] = find(fa[x]);
return fa[x];
}
public:
int numIslands(vector<vector<char>>& grid) {
int n = grid.size(), m = grid[0].size();
for (int i=0; i<=n*m; i++) siz[i]=1, fa[i]=i;
for (int i=0; i<n;i++) {
for (int j=0; j<m; j++) {
if (grid[i][j]=='1') {
if (i>0 && grid[i-1][j]=='1') merge(i*m+j, (i-1)*m+j);
if (i<n-1 && grid[i+1][j] == '1') merge(i*m+j, (i+1)*m+j);
if (j>0 && grid[i][j-1]=='1') merge(i*m+j,i*m+j-1);
if (j<m-1 && grid[i][j+1]=='1') merge(i*m+j, i*m+j+1);
}
}
}
int cnt = 0;
for (int i=0;i<n*m;i++) {
//printf("%d:%d\t", i, fa[i]);
if(fa[i]==i) cnt+=1;
}
for (int i=0;i<n;i++) {
for(int j=0;j<m;j++) {
if (grid[i][j]=='0') cnt-=1;
}
}
return cnt;
}
};