题目

类型:BFS
难度:中等
image.png

解题思路

  • 深度/广度 优先搜索

扫描整个二维网格。如果一个位置为 1,则将其加入队列,开始进行广度/深度优先搜索。
在广度/深度优先搜索的过程中,每个搜索到的 1 都会被重新标记为 0。直到队列为空,搜索结束,这样就保证连着的1只算作一个岛屿。
最终岛屿的数量就是进行搜索的次数。

  • 并查集

扫描整个二维网格。如果一个位置为 11,则将其与相邻四个方向上的 11 在并查集中进行合并。最终岛屿的数量就是并查集中连通分量的数目。

代码

1、深度优先

  1. class Solution {
  2. void dfs(char[][] grid, int r, int c) {
  3. int nr = grid.length;
  4. int nc = grid[0].length;
  5. if (r < 0 || c < 0 || r >= nr || c >= nc || grid[r][c] == '0') {
  6. return;
  7. }
  8. grid[r][c] = '0';
  9. dfs(grid, r - 1, c);
  10. dfs(grid, r + 1, c);
  11. dfs(grid, r, c - 1);
  12. dfs(grid, r, c + 1);
  13. }
  14. public int numIslands(char[][] grid) {
  15. if (grid == null || grid.length == 0) {
  16. return 0;
  17. }
  18. int nr = grid.length;
  19. int nc = grid[0].length;
  20. int num_islands = 0;
  21. for (int r = 0; r < nr; ++r) {
  22. for (int c = 0; c < nc; ++c) {
  23. if (grid[r][c] == '1') {
  24. ++num_islands;
  25. dfs(grid, r, c);
  26. }
  27. }
  28. }
  29. return num_islands;
  30. }
  31. }

2、广度优先

  1. class Solution {
  2. public int numIslands(char[][] grid) {
  3. if (grid == null || grid.length == 0) {
  4. return 0;
  5. }
  6. int nr = grid.length;
  7. int nc = grid[0].length;
  8. int num_islands = 0;
  9. for (int r = 0; r < nr; ++r) {
  10. for (int c = 0; c < nc; ++c) {
  11. if (grid[r][c] == '1') {
  12. ++num_islands;
  13. grid[r][c] = '0';
  14. Queue<Integer> neighbors = new LinkedList<>();
  15. neighbors.add(r * nc + c);
  16. while (!neighbors.isEmpty()) {
  17. int id = neighbors.remove();
  18. int row = id / nc;
  19. int col = id % nc;
  20. if (row - 1 >= 0 && grid[row-1][col] == '1') {
  21. neighbors.add((row-1) * nc + col);
  22. grid[row-1][col] = '0';
  23. }
  24. if (row + 1 < nr && grid[row+1][col] == '1') {
  25. neighbors.add((row+1) * nc + col);
  26. grid[row+1][col] = '0';
  27. }
  28. if (col - 1 >= 0 && grid[row][col-1] == '1') {
  29. neighbors.add(row * nc + col-1);
  30. grid[row][col-1] = '0';
  31. }
  32. if (col + 1 < nc && grid[row][col+1] == '1') {
  33. neighbors.add(row * nc + col+1);
  34. grid[row][col+1] = '0';
  35. }
  36. }
  37. }
  38. }
  39. }
  40. return num_islands;
  41. }
  42. }

3、并查集

class Solution {
    class UnionFind {
        int count;
        int[] parent;
        int[] rank;

        public UnionFind(char[][] grid) {
            count = 0;
            int m = grid.length;
            int n = grid[0].length;
            parent = new int[m * n];
            rank = new int[m * n];
            for (int i = 0; i < m; ++i) {
                for (int j = 0; j < n; ++j) {
                    if (grid[i][j] == '1') {
                        parent[i * n + j] = i * n + j;
                        ++count;
                    }
                    rank[i * n + j] = 0;
                }
            }
        }

        public int find(int i) {
            if (parent[i] != i) parent[i] = find(parent[i]);
            return parent[i];
        }

        public void union(int x, int y) {
            int rootx = find(x);
            int rooty = find(y);
            if (rootx != rooty) {
                if (rank[rootx] > rank[rooty]) {
                    parent[rooty] = rootx;
                } else if (rank[rootx] < rank[rooty]) {
                    parent[rootx] = rooty;
                } else {
                    parent[rooty] = rootx;
                    rank[rootx] += 1;
                }
                --count;
            }
        }

        public int getCount() {
            return count;
        }
    }

    public int numIslands(char[][] grid) {
        if (grid == null || grid.length == 0) {
            return 0;
        }

        int nr = grid.length;
        int nc = grid[0].length;
        int num_islands = 0;
        UnionFind uf = new UnionFind(grid);
        for (int r = 0; r < nr; ++r) {
            for (int c = 0; c < nc; ++c) {
                if (grid[r][c] == '1') {
                    grid[r][c] = '0';
                    if (r - 1 >= 0 && grid[r-1][c] == '1') {
                        uf.union(r * nc + c, (r-1) * nc + c);
                    }
                    if (r + 1 < nr && grid[r+1][c] == '1') {
                        uf.union(r * nc + c, (r+1) * nc + c);
                    }
                    if (c - 1 >= 0 && grid[r][c-1] == '1') {
                        uf.union(r * nc + c, r * nc + c - 1);
                    }
                    if (c + 1 < nc && grid[r][c+1] == '1') {
                        uf.union(r * nc + c, r * nc + c + 1);
                    }
                }
            }
        }

        return uf.getCount();
    }
}