【LeetCode】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;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章