200. 岛屿数量(BFS+并查集)

200. 岛屿数量

给你一个由 '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'

解法一:(BFS)

复制代码
 1 class Solution {
 2 public:
 3     static constexpr int g_direciton[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
 4     void bfs(const vector<vector<char>> &grid, int x, int y, vector<vector<bool>> &visited) {
 5         int row = grid.size();
 6         int col = grid[0].size();
 7         queue<std::pair<int, int>> q;
 8         q.push(make_pair(x, y));
 9         visited[x][y] = true;
10         while (!q.empty()) {
11             int size = q.size();
12             for (int i = 0; i < size; i++) {
13                 std::pair<int, int> tmp = q.front();
14                 q.pop();
15                 for (int j = 0; j < 4; j++) {
16                     int xNext = tmp.first + g_direciton[j][0];
17                     int yNext = tmp.second + g_direciton[j][1];
18                     if ((xNext >= 0 && xNext < row) && (yNext >= 0 && yNext < col) && 
19                         !visited[xNext][yNext] && (grid[xNext][yNext] == '1')) {
20                         q.push(make_pair(xNext, yNext));
21                         visited[xNext][yNext] = true;
22                     }
23                 }
24             }
25         }
26     }
27     int numIslands(vector<vector<char>>& grid) {
28         if (grid.size() == 0 || grid[0].size() == 0) {
29             return 0;
30         }
31         int row = grid.size();
32         int col = grid[0].size();
33         vector<vector<bool>> visited(row, vector<bool>(col, false));
34         int cnt = 0;
35         for (int i = 0; i < row; i++) {
36             for (int j = 0; j < col; j++) {
37                 if (grid[i][j] == '0') {
38                     continue;
39                 }
40                 if (visited[i][j]) {
41                     continue;
42                 }
43                 bfs(grid, i, j, visited);
44                 cnt++;
45             }
46         }
47         return cnt;
48     }
49 };
复制代码

 

解法二:(并查集)

复制代码
 1 class UnionFind {
 2 public:
 3     void initUnionFind(vector<vector<char>> &grid) {
 4         int row = grid.size();
 5         int col = grid[0].size();
 6         int n = row * col;
 7         parent.resize(n);
 8         cnt = 0;
 9         for (int i = 0; i < row; i++) {
10             for (int j = 0; j < col; j++) {
11                 int index = i * col + j; // 二维转一维
12                 parent[index] = index;
13                 if (grid[i][j] == '1') {
14                     cnt++; // 初始时岛屿的数量为陆地数量(数值为1)
15                 }
16             }
17         }
18     }
19     int findRoot(int x) {
20         if (parent[x] == x) {
21             return parent[x];
22         }
23         parent[x] = findRoot(parent[x]); // 递归找到x的根节点
24         return parent[x];
25     }
26     void unify(int x, int y) {
27         int xRoot = findRoot(x);
28         int yRoot = findRoot(y);
29         if (xRoot == yRoot) {
30             return;
31         }
32         parent[xRoot] = yRoot;
33         cnt--;
34     }
35     int getConnectedCnt() {
36         return cnt;
37     }
38 private:
39     vector<int> parent;
40     int cnt; // 连通分量数
41 };
42 class Solution : UnionFind {
43 public:
44     int numIslands(vector<vector<char>>& grid) {
45         if (grid.size() == 0 || grid[0].size() == 0) {
46             return 0;
47         }
48         initUnionFind(grid);
49         int row = grid.size();
50         int col = grid[0].size();
51         for (int i = 0; i < row; i++) {
52             for (int j = 0; j < col; j++) {
53                 int index = i * col + j;
54                 if (grid[i][j] == '1') {
55                     // 左右为1的岛屿合并
56                     if ((i + 1 < row) && grid[i + 1][j] == '1') {
57                         unify(index, (i + 1) * col + j);
58                     }
59                     // 上下为1的岛屿合并
60                     if ((j + 1 < col) && grid[i][j + 1] == '1') {
61                         unify(index, i * col + j + 1);
62                     }
63                 }
64             }
65         }
66         return getConnectedCnt();
67     }
68 };
复制代码

 

posted @   跳动的休止符  阅读(42)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示