LeetCode200岛屿数量

题目:

给你一个由 '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();
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值