200. 岛屿数量(BFS | DFS)

题目:200. 岛屿数量

public class NumIslands_200 {

    public static void main(String[] args) {

        char[][] grid = {
                { '1', '1', '1', '1', '0' },
                { '1', '1', '0', '1', '0' },
                { '1', '1', '0', '0', '0' },
                { '0', '0', '0', '0', '0' }};

        System.out.println(numIslands(grid));
    }

    /** 网格 */
    private static char[][] grid;

    /** 网格行数 */
    private static int row;

    /** 网格列数 */
    private static int col;

    /** 标记数组:标记格子是否访问过 */
    private static boolean[][] marked;

    /** 方向数组:上下左右 */
    private static final int[][] directions = {
                                    { -1, 0 },
                                    { 0, 1 },
                                    { 1, 0 },
                                    { 0, -1 }};

    /** 队列 */
    private static LinkedList<Integer> queue = new LinkedList<>();

    /**
     * 获取岛屿的数量
     * @param grid 网格
     * @return 网格中岛屿的数量
     */
    public static int numIslands(char[][] grid) {

        row = grid.length;
        // 如果数组为空,直接返回
        if (row == 0) {
            return 0;
        }

        col = grid[0].length;
        // 使用成员变量,避免来回传递数组
        NumIslands_200.grid = grid;

        // 初始化访问标记数组
        marked = new boolean[row][col];
        // 岛屿数量
        int res = 0;

        // 遍历网格数组
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                // 未被访问,并且是陆地的时候
                if (!marked[i][j] && grid[i][j] == '1') {
                    // 广度优先搜索
//                    bfs(i, j);
                    // 深度优先搜索
                    dfs(i, j);
                    res++;
                }
            }
        }

        return res;
    }

    /**
     * 广度优先搜索
     * @param i 网格的行坐标
     * @param j 网格的列坐标
     */
    public static void bfs(int i, int j) {

        // 先置为访问
        marked[i][j] = true;
        // 坐标转换成值入队列
        queue.addLast(i * col + j);

        while (!queue.isEmpty()) {
            // 头节点出队
            int head = queue.removeFirst();

            // 还原坐标
            int headX = head / col;
            int headY = head % col;

            // 探索四个方向是否是陆地
            for (int k = 0; k < 4; k++) {
                int newX = headX + directions[k][0];
                int newY = headY + directions[k][1];
                // 未越界,未被访问,并且是陆地的时候
                if (isInArea(newX, newY) && !marked[newX][newY] && grid[newX][newY] == '1') {
                    // 节点入队列
                    queue.addLast(newX * col + newY);
                    // 当前节点置为访问
                    marked[newX][newY] = true;
                }
            }
        }
    }

    /**
     * 深度优先搜索
     * @param i 网格的行坐标
     * @param j 网格的列坐标
     */
    private static void dfs(int i, int j) {
        marked[i][j] = true;
        // 探索四个方向是否是陆地
        for (int k = 0; k < 4; k++) {
            int newX = i + directions[k][0];
            int newY = j + directions[k][1];
            // 未越界,未被访问,并且是陆地的时候
            if (isInArea(newX, newY) && !marked[newX][newY] && grid[newX][newY] == '1') {
                // 递归遍历
                dfs(newX, newY);
            }
        }
    }

    /**
     * 判断坐标 (x, y) 是否在网格内
     * @param x 行坐标
     * @param y 列坐标
     * @return true 在网格内
     */
    public static boolean isInArea(int x, int y) {

        return 0 <= x && x < row && 0 <= y && y < col;
    }
}
posted @ 2020-05-14 16:42  ageovb  阅读(34)  评论(0编辑  收藏  举报