题目

分析
思路一
正向去做,使用并查集算法。也就是说去遍历每个元素,把相连的陆地加入同一个集合,然后将总的块数减一,最后减去水块数就是岛屿数。
关于并查集,我是看的卡尔的视频。
代码
cpp
class UnionFind {
private:
vector<int> parent;
vector<int> rank;
int count; // 连通分量数量
public:
UnionFind(int size) {//初始化
parent.resize(size);
rank.resize(size, 0);
count = size;
for (int i = 0; i < size; i++) {
parent[i] = i;
}
}
int find(int x) {//寻找根节点,带路径优化
if (parent[x] != x) {
parent[x] = find(parent[x]);
}
return parent[x];
}
void unite(int x, int y) {//对两块陆地进行可能的合并操作
int rootX = find(x), rootY = find(y);
if (rootX != rootY) {
if (rank[rootX] < rank[rootY]) {
parent[rootX] = rootY;
} else if (rank[rootX] > rank[rootY]) {
parent[rootY] = rootX;
} else {
parent[rootY] = rootX;
rank[rootX]++;
}
count--;//总块数--,这个数后面减去水块数就是岛屿块
}
}
int getCount() const {
return count;
}
};
class Solution {
public:
int numIslands(vector<vector<char>>& grid) {
if (grid.empty() || grid[0].empty()) return 0;
int m = grid.size(), n = grid[0].size();
UnionFind uf(m * n);
int waterCount = 0; // 水格子的数量
// 方向数组:上下左右
vector<pair<int, int>> directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == '0') {
waterCount++;
continue;
}
// 检查四个方向
for (auto& dir : directions) {
int ni = i + dir.first;
int nj = j + dir.second;
if (ni >= 0 && ni < m && nj >= 0 && nj < n && grid[ni][nj] == '1') {
uf.unite(i * n + j, ni * n + nj);
}
}
}
}
return uf.getCount() - waterCount;
}
};
结果

思路二
反向来做,遇到可能是岛屿的陆地,就消去它,此时岛屿数量加一,在岛屿数量加1以后,递归地检查周围是否有陆地,如果有,那么就消去它们,所以只要检查到有一个可能的岛屿路地块,那么他以及周围的陆地块都会被消除,再遍历后面的块时,只要是新的陆地块就一定是另外独立的岛屿。
代码
cpp
class Solution {
public:
int numIslands(vector<vector<char>>& grid)
{
int counter = 0;
for(int i=0; i<grid.size(); i++)
{
for(int j=0; j<grid[0].size(); j++)
{
if(grid[i][j]=='1')
{
searchIsland(grid, i, j);//检查到新的独立陆地
++counter;
}
}
}
return counter;
}
void searchIsland(vector<vector<char>>& grid, int i, int j)
{//递归地消去周围陆地
grid[i][j]='0';
if(i>0 && grid[i-1][j]=='1') searchIsland(grid, i-1, j);
if(j>0 && grid[i][j-1]=='1') searchIsland(grid, i, j-1);
if(i<grid.size()-1 && grid[i+1][j]=='1') searchIsland(grid, i+1, j);
if(j<grid[0].size()-1 && grid[i][j+1]=='1') searchIsland(grid, i, j+1);
}
};