岛屿数量

给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。

示例 1:

输入:grid = [
["1","1","1","1","0"],
["1","1","0","1","0"],
["1","1","0","0","0"],
["0","0","0","0","0"]
]
输出:1
示例 2:

输入:grid = [
["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]
]
输出:3

提示:

m == grid.length
n == grid[i].length
1 <= m, n <= 300
grid[i][j] 的值为 '0' 或 '1'

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/number-of-islands
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

遍历矩阵中的所有点,对于岛屿使用广度优先搜索or深度优先搜索or并查集找到一个小岛。BFS和DFS的时间复杂度是O(M * N),使用了路径压缩的并查集时间复杂度接近常数,时间复杂度也是O(M * N)。

code 广度优先搜索

class Solution {
public:
    typedef pair<int,int> PII;
    int dx[4] = {-1,1,0,0};
    int dy[4] = {0,0,-1,1};

    int numIslands(vector<vector<char>>& grid) {

       int m = grid.size(),n = grid[0].size();

       vector<vector<int>> visit(m,vector<int>(n,0));

       int ans = 0;
       for(int i = 0;i < m;i ++)
       {
           for(int j = 0;j < n;j++)
           {
               if(grid[i][j] == '1' && !visit[i][j])
               {
                   ans ++;
                   queue<PII> q;
                   q.push({i,j});
				  //入队表明已经走过
                   visit[i][j] = 1;
                   while(!q.empty())
                   {
                       PII cur = q.front();
                       q.pop();
                       for(int k = 0;k < 4;k++)
                       {
                           int x = cur.first + dx[k];
                           int y = cur.second + dy[k];
                           if(x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == '1' && !visit[x][y])
                           {
                               visit[x][y] = 1;
                               q.push({x,y});
                           }
                       }
                   }
               }
           }
       } 

       return ans;
    }
};

code 并查集

class Solution {
public:
    //并查集
    //将所有相邻的1归为一个集合
    //将每一个点映射到0-m * n 的空间上
    //每次查询四周是不是同一个集合,不是则合并
    int dx[4] = {-1,1,0,0};
    int dy[4] = {0,0,-1,1};

    int find(int x,int p[])
    {
        if(p[x] != x) p[x] = find(p[x],p);

        return p[x];
    }


    int numIslands(vector<vector<char>>& grid) {
        int m = grid.size(),n = grid[0].size();

        int p[m * n];

        for(int i = 0;i < m * n;i ++) p[i] = i;

        for(int i = 0;i < m;i ++)
        {
            for(int j = 0;j < n;j ++)
            {
                if(grid[i][j] == '1')
                {
                    //遍历四周的点
                    for(int k = 0;k < 4;k ++)
                    {
                        int x = i + dx[k];
                        int y = j + dy[k];
                        if(x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == '1')
                        {
                            //如果和当前点不是同一个集合,合并
                            int roota = find(i * n + j,p);
                            int rootb = find(x * n + y,p);
                            if(roota != rootb)
                            {
                                p[rootb] = roota;
                            }
                        }
                    }
                }
            }
        }

        int ans = 0;
        for(int i = 0;i < m;i ++)
        {
            for(int j = 0;j < n;j ++)
            {
                if(grid[i][j] == '1' && p[i * n + j] == i * n + j) ans ++;
            }
        }
        return ans;    
    }
};
posted on 2023-03-03 17:05  huangxk23  阅读(22)  评论(0)    收藏  举报