题目:
给你一个由 '1'
(陆地)和 '0'
(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
①第一种方法DFS
1 1 0 0 0
1 1 0 0 0
0 0 1 0 0
0 0 0 1 1
通过指针访问grid数组,当访问到1时,将1改为0,并将其上下左右所有的1都变为0,避免重复访问
0 0 0 0 0
0 0 0 0 0
0 0 1 0 0
0 0 0 1 1
继续移动指针,直到再次找到1为止,如此进行此操作,直到访问完此数组.
class Solution {
public:
void dfs(vector<vector<char>>& grid,int r,int c)
{
int row=grid.size();
int col=grid[0].size();
grid[r][c]='0';
if(r-1>=0&&grid[r-1][c]=='1') dfs(grid,r-1,c);
if(r+1<row&&grid[r+1][c]=='1') dfs(grid,r+1,c);
if(c-1>=0&&grid[r][c-1]=='1') dfs(grid,r,c-1);
if(c+1<col&&grid[r][c+1]=='1') dfs(grid,r,c+1);
}
int numIslands(vector<vector<char>>& grid) {
int row=grid.size();
if(!row) return 0;
int res=0;
int col=grid[0].size();
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
if(grid[i][j]=='1'){
++res;
dfs(grid,i,j);
}
}
}
return res;
}
};
②第二种方法BFS
BFS是利用队列的特性进行搜素
当指针指向的值为1时,把当前的坐标进入队列当中,同时将值改为 0,对其上下左右进行判断,如果值为1,则将其对应的坐标入队
class Solution {
public:
//BFS
int numIslands(vector<vector<char>>& grid) {
int row=grid.size();
if(!row) return 0;
int col=grid[0].size();
queue<pair<int,int>> q;
int res=0;
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
if(grid[i][j]=='1'){
res++;
grid[i][j]='0';
q.push({i,j});
while(!q.empty()){
auto rc=q.front();
q.pop();
int r=rc.first,c=rc.second;
if(r-1>=0&&grid[r-1][c]=='1') {
q.push({r-1,c});
grid[r-1][c]='0';
}
if(r+1<row&&grid[r+1][c]=='1') {
q.push({r+1,c});
grid[r+1][c]='0';
}
if(c-1>=0&&grid[r][c-1]=='1') {
q.push({r,c-1});
grid[r][c-1]='0';
}
if(c+1<col&&grid[r][c+1]=='1') {
q.push({r,c+1});
grid[r][c+1]='0';
}
}
}
}
}
return res;
}
};
③第三种方法并查集
并查集这个算法模板性极高,在此模板基础上增加一些新方法即可。
如果使用并查集解决此题,需要将二维数组转化成一维数组,进行union和find。
class UnionFind{
private:
int count;
vector<int> root;
vector<int> rank;
public:
UnionFind(vector<vector<char>>& grid){
count=0;
int row=grid.size();
int col=grid[0].size();
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
if(grid[i][j]=='1'){
root.push_back(i*col+j);
++count;
}else {
root.push_back(-1);
}
rank.push_back(0);
}
}
}
int find(int x)
{
if(x!=root[x]){
root[x]=find(root[x]);}
return root[x];
}
void union1(int x,int y)
{
int rootx=find(x);
int rooty=find(y);
if (rootx != rooty) {
if (rank[rootx] < rank[rooty]) {
root[rootx] = rooty;
}
else if(rank[rootx] > rank[rooty]) root[rooty] = rootx;
else
{
root[rooty] = rootx;
rank[rootx] += 1;
}
--count;
}
}
int getCount ()const
{
return count;
}
};
class Solution {
public:
//并查集
int numIslands(vector<vector<char>>& grid) {
int row=grid.size();
if(!row) return 0;
int col=grid[0].size();
UnionFind uf(grid);
for(int i=0;i<row;i++)
{
for(int j=0;j<col;j++){
if(grid[i][j]=='1'){
grid[i][j]='0';
if(i-1>=0&&grid[i-1][j]=='1') uf.union1(i*col+j,(i-1)*col+j);
if(i+1<row&&grid[i+1][j]=='1') uf.union1(i*col+j,(i+1)*col+j);
if(j-1>=0&&grid[i][j-1]=='1') uf.union1(i*col+j,i*col+j-1);
if(j+1<col&&grid[i][j+1]=='1') uf.union1(i*col+j,i*col+j+1);
}
}
}
return uf.getCount();
}
};