LC200—岛屿数量

2023-09-25 16:08:35 浏览数 (1)

200. 岛屿数量

难度中等1021

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

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

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

示例 1:

代码语言:javascript复制
输入:grid = [
  ["1","1","1","1","0"],
  ["1","1","0","1","0"],
  ["1","1","0","0","0"],
  ["0","0","0","0","0"]
]
输出:1

详细解析

DFS1

代码语言:javascript复制
class Solution {
   
   public int numIslands(char[][] grid) {
   
    //边界条件判断
    if (grid == null || grid.length == 0)
        return 0;
    //统计岛屿的个数
    int count = 0;
    //两个for循环遍历每一个格子
    for (int i = 0; i < grid.length; i  )
        for (int j = 0; j < grid[0].length; j  ) {
   
            //只有当前格子是1才开始计算
            if (grid[i][j] == '1') {
   
                //如果当前格子是1,岛屿的数量加1
                count  ;
                //然后通过dfs把当前格子的上下左右4
                //个位置为1的都要置为0,因为他们是连着
                //一起的算一个岛屿,
                dfs(grid, i, j);
            }
        }
    //最后返回岛屿的数量
    return count;
}

//这个方法会把当前格子以及他邻近的为1的格子都会置为1
public void dfs(char[][] grid, int i, int j) {
   
    //边界条件判断,不能越界
    if (i < 0 || i >= grid.length || j < 0 || j >= grid[0].length || grid[i][j] == '0')
        return;
    //把当前格子置为0,然后再从他的上下左右4个方向继续遍历
    grid[i][j] = '0';
    dfs(grid, i - 1, j);//上
    dfs(grid, i   1, j);//下
    dfs(grid, i, j   1);//左
    dfs(grid, i, j - 1);//右
}

}

DFS2

代码语言:javascript复制
package com.nie.o3;/* * *@auth wenzhao *@date 2021/3/8 21:23 */

public class LEE200 {
   
    private static final int[][] DIR = {
   {
   -1, 0}, {
   0, 1}, {
   0, -1,}, {
   1, 0}};
    private boolean[][] visited;
    private int rows;
    private int cols;
    private char[][] grid;

    public int numIsland(char[][] grid) {
   
        this.rows = grid.length;
        this.cols = grid[0].length;
        if (rows == 0) {
   
            return 0;
        }
        this.visited = new boolean[rows][cols];
        int count = 0;
        this.grid = grid;
        for (int i = 0; i < rows; i  ) {
   
            for (int j = 0; j < cols; j  ) {
   
                if (grid[i][j] == '1' & !visited[i][j]) {
   
                    dfs(i, j);
                    count  ;
                }
            }
        }
        return count;
    }

    private void dfs(int i, int j) {
   
        visited[i][j] = true;
        for (int k = 0; k < DIR.length; k  ) {
   
            int newX = i   DIR[k][0];
            int newY = j   DIR[k][1];

            // 如果不越界、还是陆地、没有被访问过
            if (inArea(newX, newY) && grid[newX][newY] == '1' && !visited[newX][newY]) {
   
                dfs(newX, newY);
            }

        }
    }

    private boolean inArea(int x, int y) {
   
        return x >= 0 && x < rows && y >= 0 && y < cols;
    }

}

并查集

代码语言:javascript复制
public class Solution {
   

    private int rows;
    private int cols;

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

        // 空地的数量
        int spaces = 0;
        UnionFind unionFind = new UnionFind(rows * cols);
        int[][] directions = {
   {
   1, 0}, {
   0, 1}};
        for (int i = 0; i < rows; i  ) {
   
            for (int j = 0; j < cols; j  ) {
   
                if (grid[i][j] == '0') {
   
                    spaces  ;
                } else {
   
                    // 此时 grid[i][j] == '1'
                    for (int[] direction : directions) {
   
                        int newX = i   direction[0];
                        int newY = j   direction[1];
                        // 先判断坐标合法,再检查右边一格和下边一格是否是陆地
                        if (newX < rows && newY < cols && grid[newX][newY] == '1') {
   
                            unionFind.union(getIndex(i, j), getIndex(newX, newY));
                        }
                    }
                }
            }
        }
        return unionFind.getCount() - spaces;
    }

    private int getIndex(int i, int j) {
   
        return i * cols   j;
    }

    private class UnionFind {
   
        /** * 连通分量的个数 */
        private int count;
        private int[] parent;

        public int getCount() {
   
            return count;
        }

        public UnionFind(int n) {
   
            this.count = n;
            parent = new int[n];
            for (int i = 0; i < n; i  ) {
   
                parent[i] = i;
            }
        }

        private int find(int x) {
   
            while (x != parent[x]) {
   
                parent[x] = parent[parent[x]];
                x = parent[x];
            }
            return x;
        }

        public void union(int x, int y) {
   
            int xRoot = find(x);
            int yRoot = find(y);
            if (xRoot == yRoot) {
   
                return;
            }

            parent[xRoot] = yRoot;
            count--;
        }
    }
}

0 人点赞