image.png

思路1:BFS

  • 逐个扫描矩阵,如果发现有1,那么计数器cnt就 +1
  • 然后将这个发现的1的所有相邻的1全部变成0
  • 逐个重复这个操作
  • 需要注意的是,BFS在将新节点插入的时候就要改变数值,否则会有重复扫描的问题。

代码1:

  1. class Solution {
  2. public:
  3. int dx[4] = {0, 1, 0, -1};
  4. int dy[4] = {1, 0, -1, 0};
  5. void bfs(vector<vector<char>>& grid, int x, int y, int row, int col) {
  6. queue<pair<int, int>> queue_pos;
  7. queue_pos.push({x, y});
  8. while (!queue_pos.empty()) {
  9. int cur_level_size = queue_pos.size();
  10. for (int i = 0; i < cur_level_size; ++i) {
  11. pair<int, int> cur_pos = queue_pos.front();
  12. queue_pos.pop();
  13. int cur_x = cur_pos.first;
  14. int cur_y = cur_pos.second;
  15. //grid[cur_x][cur_y] = '0';
  16. // 考虑将新节点放到树上
  17. for (int i = 0; i < 4; i++) {
  18. int next_x = cur_x + dx[i];
  19. int next_y = cur_y + dy[i];
  20. if (next_x < 0 || next_x >= row || next_y < 0 || next_y >= col || grid[next_x][next_y] == '0') {
  21. continue;
  22. } else {
  23. // 此处的0起到标记的作用,防止重复访问
  24. grid[next_x][next_y] = '0';
  25. queue_pos.push({next_x, next_y});
  26. }
  27. }
  28. }
  29. }
  30. }
  31. int numIslands(vector<vector<char>>& grid) {
  32. if (!grid.size()) {
  33. return 0;
  34. }
  35. int cnt = 0;
  36. int row = grid.size();
  37. int col = grid[0].size();
  38. for (int i = 0; i < row; i++) {
  39. for (int j = 0; j < col; j++) {
  40. if (grid[i][j] == '1') {
  41. cnt++;
  42. bfs(grid, i, j, row, col);
  43. }
  44. // cout << grid[i][j] << " ";
  45. }
  46. // cout << endl;
  47. }
  48. return cnt;
  49. }
  50. };

思路2:栈式DFS

  • 在弹栈的时候加入序列(也就是变成0)
  • 和先序遍历二叉树的思路一样
  • 根节点先入栈,然后弹栈,最后将可能的节点都加入栈中
  • 脑子里面要有图,不然记不住。

    代码2:

    1. class Solution {
    2. public:
    3. void stackDfs(vector<vector<char>>&grid, int x, int y, int row, int col) {
    4. int dx[4] = {1, 0, -1, 0};
    5. int dy[4] = {0, -1, 0, 1};
    6. stack<pair<int, int>> stack_islands;
    7. stack_islands.push({x, y});
    8. while (!stack_islands.empty()) {
    9. // 出栈时加入遍历序列(这里就是变成0了)
    10. pair<int, int> cur_pos = stack_islands.top();
    11. int cur_x = cur_pos.first, cur_y = cur_pos.second;
    12. stack_islands.pop();
    13. grid[cur_x][cur_y] = '0';
    14. // 入栈
    15. for (int i = 0; i < 4; ++i) {
    16. int next_x = cur_x + dx[i], next_y = cur_y + dy[i];
    17. if (next_x >= 0 && next_x < row && next_y >= 0 && next_y < col && grid[next_x][next_y] == '1') {
    18. stack_islands.push({next_x, next_y});
    19. }
    20. }
    21. }
    22. }
    23. int numIslands(vector<vector<char>>& grid) {
    24. int row = grid.size();
    25. int col = grid[0].size();
    26. int count_islands = 0;
    27. for (int i = 0; i < row; ++i) {
    28. for (int j = 0; j < col; ++j) {
    29. if (grid[i][j] == '1') {
    30. count_islands++;
    31. stackDfs(grid, i, j, row, col);
    32. }
    33. }
    34. }
    35. return count_islands;
    36. }
    37. };

    思路3:并查集

  • 利用node(i, j) = i * col + j将二维的点变成一维的数字

  • 遍历grid当中每一个元素,如果是'1',那么就和它上下左右所有的‘1’放到一个集合当中。
  • 遍历grid当中每一个元素,如果find(node(i,j)) == node(i, j) && grid[i][j] == 1,说明一定是一个新的集合。统计个数即可。
  • 并查集操作可以按秩进行优化。

    代码3:

    1. class Solution {
    2. private:
    3. int row, col;
    4. unordered_map<int, int> fa, r;
    5. int dx[4] = {0, 1, 0, -1};
    6. int dy[4] = {1, 0, -1, 0};
    7. public:
    8. bool check_boundary(int x, int y) {
    9. if (0 <= x && x <= row - 1 && 0 <= y && y <= col - 1) {
    10. return true;
    11. } else {
    12. return false;
    13. }
    14. }
    15. void init(int n) {
    16. for (int i = 0; i <= n; i++) {
    17. fa[i] = i;
    18. r[i] = 1;
    19. }
    20. }
    21. int find(int x) {
    22. if (x == fa[x]) {
    23. return x;
    24. } else {
    25. fa[x] = find(fa[x]);
    26. return fa[x];
    27. }
    28. }
    29. void merge(int i, int j) {
    30. int x = find(i);
    31. int y = find(j);
    32. if (x != y) {
    33. if (r[x] <= r[y]) {
    34. fa[x] = y;
    35. } else {
    36. fa[y] = x;
    37. }
    38. if (r[x] == r[y]) {
    39. r[y] += 1;
    40. }
    41. }
    42. }
    43. int node(int i, int j) {
    44. return i * col + j;
    45. }
    46. int numIslands(vector<vector<char>>& grid) {
    47. row = grid.size(), col = grid[0].size();
    48. init(row * col + 5);
    49. for (int i = 0; i < row; i++) {
    50. for (int j = 0; j < col; j++) {
    51. if (grid[i][j] == '1') {
    52. for (int k = 0; k < 4; k++) {
    53. int ni = i + dx[k], nj = j + dy[k];
    54. if (check_boundary(ni, nj) && grid[ni][nj] == '1') {
    55. merge(node(i, j), node(ni, nj));
    56. }
    57. }
    58. }
    59. }
    60. }
    61. int cnt = 0;
    62. for (int i = 0; i < row; i++) {
    63. for (int j = 0; j < col; j++) {
    64. if (find(node(i, j)) == node(i, j) && grid[i][j] == '1') {
    65. cnt += 1;
    66. }
    67. }
    68. }
    69. return cnt;
    70. }
    71. };