我正在解决LeetCode.com上一个名为 Number of Islands 的问题:
给定一个表示“1”(陆地)和“0”(水)的地图的 mxn 2D 二进制网格网格,返回岛屿的数量。岛屿四面环水,由相邻陆地水平或垂直连接而成。您可以假设网格的所有四个边缘都被水包围。
我知道如何用 DFS 解决它,但我正在学习union-find并提出以下方法:
class Solution {
public:
vector<int> parent, sz;
int counter;
int find(int i) {
if(parent[i]==i) return i;
return parent[i]=find(parent[i]);
}
void unionf(int one, int two) {
int p1=find(one);
int p2=find(two);
if(p1==p2) return;
if(sz[one]<sz[two]) {
parent[one]=two;
sz[two]+=sz[one];
} else {
parent[two]=one;
sz[one]+=sz[two];
}
counter--;
}
int numIslands(vector<vector<char>>& grid) {
int m=grid.size(), n=grid[0].size();
parent.resize(m*n);
iota(begin(parent),end(parent),0);
sz.resize(m*n,1);
counter=0;
for(int i=0; i<m; i++) {
for(int j=0; j<n; j++) {
if(grid[i][j]=='0') {
continue;
}
//grid[i][j]=='1'; an island
counter++;
int idx=i*n+j;
//traverse all 4 neighbors
if(i+1<m && grid[i+1][j]=='1') unionf(idx,(i+1)*n+j);
if(i-1>=0 && grid[i-1][j]=='1') unionf(idx, (i-1)*n+j);
if(j+1<n && grid[i][j+1]=='1') unionf(idx, i*n+j+1);
if(j-1>=0 && grid[i][j-1]=='1') unionf(idx, i*n+j-1);
}
}
return counter;
}
};
它对样本输入产生正确的答案,但对[["1","1","1"],["0","1","0"],["1","1","1"]]
.
在高层次上,我的逻辑是每当我遇到一个岛(1
)时,我都会增加计数器并调用unionf()
并尝试将它与它的邻居统一起来。如果这样的统一是可能的,我会减少counter
,unionf()
因为它链接到它的父岛(一个连接的组件)而不是一个新岛。
有人可以指出我的逻辑中缺少什么吗?谢谢!