一、题目

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

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

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

点击查看原题
难度级别: 中等

二、思路

1)DFS

使用visited记录进行深度搜索过的空格,不会重复计数岛屿(这里可以使用原本的数组空间进行优化,这里本着不想更改源数据的想法进行编码),每进行一次dfs,岛屿数量自增一

2)并查集

并查集可以将连在一起的格子都指向一个根节点,将二维数组一维化,就可以使用并查集进行解题

三、代码

1)DFS

  1. class Solution {
  2. private boolean[][] visited;
  3. private int[][] dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
  4. public int numIslands(char[][] grid) {
  5. visited = new boolean[grid.length][grid[0].length];
  6. int ans = 0;
  7. for (int i = 0; i < grid.length; i++) {
  8. for (int j = 0; j < grid[0].length; j++) {
  9. if (visited[i][j] == false && grid[i][j] == '1') {
  10. dfs(grid, i, j);
  11. ans++;
  12. }
  13. }
  14. }
  15. return ans;
  16. }
  17. public void dfs(char[][] grid, int row, int col) {
  18. if (grid[row][col] == '0') {
  19. return ;
  20. }
  21. visited[row][col] = true;
  22. for (int[] dir : dirs) {
  23. int newRow = row + dir[0];
  24. int newCol = col + dir[1];
  25. if (newRow >= 0 && newRow < grid.length
  26. && newCol >= 0 && newCol < grid[0].length
  27. && visited[newRow][newCol] == false) {
  28. dfs(grid, newRow, newCol);
  29. }
  30. }
  31. }
  32. }

时间复杂度为O(m*n),空间复杂度为O(m*n)

2)并查集

  1. class Solution {
  2. public int numIslands(char[][] grid) {
  3. int oneCnt = 0;
  4. UnionFind uf = new UnionFind(grid.length * grid[0].length);
  5. int[][] dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
  6. for (int i = 0; i < grid.length; i++) {
  7. for (int j = 0; j < grid[0].length; j++) {
  8. if (grid[i][j] == '1') {
  9. oneCnt++;
  10. for (int[] dir : dirs) {
  11. int newI = i + dir[0];
  12. int newJ = j + dir[1];
  13. if (newI >= 0 && newI < grid.length
  14. && newJ >= 0 && newJ < grid[0].length
  15. && grid[newI][newJ] == '1') {
  16. uf.union(i*grid[0].length + j, newI *grid[0].length + newJ);
  17. }
  18. }
  19. }
  20. }
  21. }
  22. return oneCnt - uf.getMeregeCnt();
  23. }
  24. }
  25. class UnionFind {
  26. private int[] ranks;
  27. private int[] parents;
  28. private int meregeCnt = 0;
  29. public UnionFind(int n) {
  30. ranks = new int[n+1];
  31. parents = new int[n+1];
  32. for (int i = 1; i < n; i++) {
  33. parents[i] = i;
  34. }
  35. }
  36. public int findParent(int x) {
  37. if (parents[x] != x) {
  38. parents[x] = findParent(parents[x]);
  39. }
  40. return parents[x];
  41. }
  42. public void union(int x, int y) {
  43. int xP = findParent(x);
  44. int yP = findParent(y);
  45. if (xP == yP) {
  46. return ;
  47. }
  48. if (ranks[xP] > ranks[yP]) {
  49. parents[yP] = xP;
  50. } else if (ranks[xP] < ranks[yP]) {
  51. parents[xP] = yP;
  52. } else {
  53. parents[yP] = xP;
  54. ranks[xP]++;
  55. }
  56. meregeCnt++;
  57. }
  58. public int getMeregeCnt() {
  59. return meregeCnt;
  60. }
  61. }

a是四次union的时间,时间复杂度为O(m*n*a),空间复杂度为O(m*n)