1. 程式人生 > 實用技巧 >LeetCode 695 島嶼的最大面積

LeetCode 695 島嶼的最大面積

LeetCode 695 島嶼的最大面積

題目描述:
給定一個包含了一些 0 和 1 的非空二維陣列 grid 。
一個 島嶼 是由一些相鄰的 1 (代表土地) 構成的組合,這裡的「相鄰」要求兩個 1 必須在水平或者豎直方向上相鄰。你可以假設 grid 的四個邊緣都被 0(代表水)包圍著。
找到給定的二維陣列中最大的島嶼面積。(如果沒有島嶼,則返回面積為 0 。)

DFS(深度優先遍歷)

執行用時:4 ms, 在所有 Java 提交中擊敗了28.45%的使用者
記憶體消耗:40.4 MB, 在所有 Java 提交中擊敗了11.25%的使用者

class Solution {
    public int maxAreaOfIsland(int[][] grid) {
        //尋找圖中最大連通分量的個數
        //每個連通分量使用DFS的方式完全標記
        if(grid==null || grid.length==0 || grid[0].length==0) {
            return 0;
        }

        int[][] directs = new int[][]{
            {0,1},{1,0},{0,-1},{-1,0}
        };

        //已訪問的連通分量中的陸地使用'2'標記
        int result = 0;
        for(int row=0; row<grid.length; row++) {
            for(int col=0; col<grid[0].length; col++) {
                if(grid[row][col]==1) {
                    result = Math.max(
                        result, dfs(grid, new int[]{row, col}, directs)
                    );
                }
            }
        }

        return result;
    }

    public int dfs(int[][] grid, int[] axis, int[][] directs) {

        /*本節點標記*/
        int result = 1;
        grid[axis[0]][axis[1]] = 2;   //已訪問
        /*向下遞迴*/
        for(int[] direct: directs) {
            int nextRow = axis[0] + direct[0];
            int nextCol = axis[1] + direct[1];
            /*剪枝: 不符合條件不向下遞迴*/
            if(nextRow>=0 && nextRow<grid.length && 
            nextCol>=0 && nextCol<grid[0].length &&
            grid[nextRow][nextCol]==1) {
                result += dfs(grid, new int[]{nextRow, nextCol}, directs);
            }
        }
        /*返回結果*/
        return result;
    }
}

沉島思想優化
轉載於github題解

執行用時:2 ms, 在所有 Java 提交中擊敗了100.00%的使用者
記憶體消耗:40 MB, 在所有 Java 提交中擊敗了73.25%的使用者

class Solution {
    public int maxAreaOfIsland(int[][] grid) {
        int res = 0; 
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[i].length; j++) {
                if (grid[i][j] == 1) {
                    res = Math.max(res, dfs(i, j, grid));
                }
            }
        } 
        return res;
    }
    // 每次呼叫的時候預設num為1,進入後判斷如果不是島嶼,則直接返回0,就可以避免預防錯誤的情況。
    // 每次找到島嶼,則直接把找到的島嶼改成0,這是傳說中的沉島思想,就是遇到島嶼就把他和周圍的全部沉默。
    // ps:如果能用沉島思想,那麼自然可以用朋友圈思想。有興趣的朋友可以去嘗試。
    private int dfs(int i, int j, int[][] grid) {
        if (i < 0 || j < 0 || i >= grid.length || j >= grid[i].length || grid[i][j] == 0) { 
            return 0;
        } 
        grid[i][j] = 0;
        int num = 1;
        num += dfs(i + 1, j, grid);
        num += dfs(i - 1, j, grid);
        num += dfs(i, j + 1, grid);
        num += dfs(i, j - 1, grid);
        return num;
        
    }
}