算法-島嶼問題專輯

遇到島嶼問題,基本上就是一種算法:深搜+記憶化搜索。

1、島嶼數量

  1. List item

200. 島嶼數量

給定一個由 '1'(陸地)和 '0'(水)組成的的二維網格,計算島嶼的數量。一個島被水包圍,並且它是通過水平方向或垂直方向上相鄰的陸地連接而成的。你可以假設網格的四個邊均被水包圍。

示例 1:

輸入:
11110
11010
11000
00000

輸出: 1
示例 2:

輸入:
11000
11000
00100
00011

輸出: 3

解題思路:深搜+記憶化搜索。
搜索過的節點不在搜索,複雜度O(m*n)

    public int numIslands(char[][] grid) {
        int count=0;
        for(int i=0;i<grid.length;i++){
            for(int j=0;j<grid[0].length;j++){
                if(grid[i][j]=='1'){
                    dfs(grid,i,j);
                    count++;
                }
            }
        }
        return count;
    }

    public void dfs(char[][] matrix,int i,int j){
        if(i<0||j<0||i>=matrix.length||j>=matrix[0].length||matrix[i][j]!='1'){
            return;
        }
        matrix[i][j]='*';//上下左右搜一遍
        dfs(matrix,i-1,j);
        dfs(matrix,i+1,j);
        dfs(matrix,i,j-1);
        dfs(matrix,i,j+1);
    }

2、被圍繞的區域

130. 被圍繞的區域

給定一個二維的矩陣,包含 'X' 和 'O'(字母 O)。

找到所有被 'X' 圍繞的區域,並將這些區域裏所有的 'O' 用 'X' 填充。

示例:

X X X X
X O O X
X X O X
X O X X
運行你的函數後,矩陣變爲:

X X X X
X X X X
X X X X
X O X X
解釋:

被圍繞的區間不會存在於邊界上,換句話說,任何邊界上的 'O' 都不會被填充爲 'X'。 任何不在邊界上,或不與邊界上的 'O' 相連的 'O' 最終都會被填充爲 'X'。如果兩個元素在水平或垂直方向相鄰,則稱它們是“相連”的。

解題思路:
1、對所有邊界上O的位置進行深搜,替換
2、所有O深搜替換爲X
3、還原1中替換的數據

     public void solve(char[][] board) {
        for (int i=0;i<board.length;i++){
            for (int j=0;j<board[0].length;j++){
                if(i==0||j==0||i==board.length-1||j==board[0].length-1){
                    dfs(board,i,j,'-','O');
                }
            }
        }
        for (int i=0;i<board.length;i++){
            for (int j=0;j<board[0].length;j++){
                dfs(board,i,j,'X','O');
            }
        }
        for (int i=0;i<board.length;i++){
            for (int j=0;j<board[0].length;j++){
                dfs(board,i,j,'O','-');
            }
        }
    }

    public void dfs(char[][] board,int i,int j,char replace,char target){
        if(i<0||j<0||i>=board.length||j>=board[0].length||board[i][j]!=target){
            return;
        }
        board[i][j]=replace;
        dfs(board,i+1,j,replace,target);
        dfs(board,i-1,j,replace,target);
        dfs(board,i,j+1,replace,target);
        dfs(board,i,j-1,replace,target);
    }

3、島嶼最大面積

695. 島嶼的最大面積

給定一個包含了一些 0 和 1 的非空二維數組 grid 。

一個 島嶼 是由一些相鄰的 1 (代表土地) 構成的組合,這裏的「相鄰」要求兩個 1 必須在水平或者豎直方向上相鄰。你可以假設 grid 的四個邊緣都被 0(代表水)包圍着。

找到給定的二維數組中最大的島嶼面積。(如果沒有島嶼,則返回面積爲 0 。)

 

示例 1:

[[0,0,1,0,0,0,0,1,0,0,0,0,0],
 [0,0,0,0,0,0,0,1,1,1,0,0,0],
 [0,1,1,0,1,0,0,0,0,0,0,0,0],
 [0,1,0,0,1,1,0,0,1,0,1,0,0],
 [0,1,0,0,1,1,0,0,1,1,1,0,0],
 [0,0,0,0,0,0,0,0,0,0,1,0,0],
 [0,0,0,0,0,0,0,1,1,1,0,0,0],
 [0,0,0,0,0,0,0,1,1,0,0,0,0]]
對於上面這個給定矩陣應返回 6。注意答案不應該是 11 ,因爲島嶼只能包含水平或垂直的四個方向的 1 。

示例 2:

[[0,0,0,0,0,0,0,0]]
對於上面這個給定的矩陣, 返回 0。

經過上面兩個題的套路,解決本題也是比較簡單.

深搜+記憶化搜索的時候記錄島嶼面積即可,然後選取一個最大值

    public int maxAreaOfIsland(int[][] grid) {
        int maxArea=0;
        if(grid.length==0||grid[0].length==0){
            return 0;
        }
        for(int i=0;i<grid.length;i++){
            for(int j=0;j<grid[0].length;j++){
                if(grid[i][j]==1){
                    maxArea=Math.max(maxArea,dfs(grid,i,j));
                }
            }
        }
        return maxArea;
    }

    public int dfs(int[][] grid,int i,int j){
        if(i<0||j<0||i>=grid.length||j>=grid[0].length||grid[i][j]!=1){
            return 0;
        }
        grid[i][j]=2;
        return 1+ dfs(grid,i+1,j)+dfs(grid,i-1,j)+dfs(grid,i,j+1)+dfs(grid,i,j-1);

    }

4、島嶼周長

463. 島嶼的周長

給定一個包含 0 和 1 的二維網格地圖,其中 1 表示陸地 0 表示水域。

網格中的格子水平和垂直方向相連(對角線方向不相連)。整個網格被水完全包圍,但其中恰好有一個島嶼(或者說,一個或多個表示陸地的格子相連組成的島嶼)。

島嶼中沒有“湖”(“湖” 指水域在島嶼內部且不和島嶼周圍的水相連)。格子是邊長爲 1 的正方形。網格爲長方形,且寬度和高度均不超過 100 。計算這個島嶼的周長。

示例 :

輸入:
[[0,1,0,0],
 [1,1,1,0],
 [0,1,0,0],
 [1,1,0,0]]

輸出: 16

解釋: 它的周長是下面圖片中的 16 個黃色的邊:

在這裏插入圖片描述

本題其實也非常簡單,想一下,每個1最多貢獻4個邊長,一旦有一個和它連接的1,它貢獻的邊長就減少一個。基於這樣的思想,我們可以在每次遍歷到1的時候,看一下它的上下左右是不是1,如果是的話,減去1。

    public int islandPerimeter(int[][] grid) {
        int count=0;
        for (int i=0;i<grid.length;i++){
            for (int j=0;j<grid[0].length;j++){
                if(grid[i][j]==1){
                    count+=4;
                    if(i>0&&grid[i-1][j]==1){//上面
                        count--;
                    }
                    if(i<grid.length-1&&grid[i+1][j]==1){//下面
                        count--;
                    }
                    if(j>0&&grid[i][j-1]==1){//左面
                        count--;
                    }
                    if(j<grid[0].length-1&&grid[i][j+1]==1){//右面
                        count--;
                    }
                }
            }
        }
        return  count;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章