Leetcode島嶼問題彙總-圖的遍歷

Leetcode島嶼問題彙總-圖的遍歷

leetcode中的島嶼問題,本質上是圖的遍歷問題,所以我們需要先了解什麼事圖的遍歷,以及一般的遍歷方法。

圖的遍歷

圖的遍歷,屬於數據結構中的內容。指的是從圖中的任一頂點出發,對圖中的所有頂點訪問一次且只訪問一次。圖的遍歷操作和樹的遍歷操作功能相似。圖的遍歷是圖的一種基本操作,圖的許多其它操作都是建立在遍歷操作的基礎之上。

圖的遍歷,分爲廣度優先搜索(Breadth First Search, BFS)深度優先搜索(Depth First Search, DFS)兩種。

廣度優先搜索

類似於樹的層次遍歷。

設從V0出發

1)訪問V0;

2)依次訪問V0的所有鄰接點V1, V2, ..., Vt;

3)依次訪問V1的所有鄰接點;

     依次訪問V2的所有鄰接點;

  ......

     依次訪問Vt的所有鄰接點;

直到所有頂點被訪問完。

注意:不能重複訪問。

根據算法的描述,我們很容易就能聯想到使用隊列來實現BFS:

(1)每訪問1個頂點後,讓該頂點的序號進隊;

(2)然後隊頭出隊,將未訪問過的鄰接點訪問後再依次進隊;

         ......

         直到隊空爲止;

僞代碼實現:

public void BFS(Vnode[] G, int v) //對圖G從序號爲v的頂點出發,按BFS遍歷
{   
    int u; 
    qtype Q; 
    ClearQueue(Q);   //置隊Q爲空
    visit(G,v); 
    visited[v] = true; //訪問頂點, 置標誌爲“已訪問” 
    EnQueue(Q, v);    //v進隊
    while (!EmptyQueue(Q))  { //隊非空時
         v = DeQueue(Q); //出隊, 隊頭送v
         u = FirstAdj(G, v); //取v的第一鄰接點序號
         while (u >= 0) {
             if (visited[u] == false) { //u未訪問過
                visit(G, u); visited[u] = true; 
                EnQueue(Q, u);
             }
             u = NextAdj(G, v, u);  //取v關於u的下一鄰接點
         }
     }
} 

深度優先搜索

類似於樹的前序遍歷。

從某個頂點出發,沿着圖的某個分支搜索直到頭,然後回溯(Backtracking),沿着另一分支搜索。

注意:不能重複訪問(圖可能有迴路,避免陷入死循環)

僞代碼實現(遞歸):

public void DFS(Vnode[] G, int v) //對圖G從序號爲v的頂點出發,按DFS搜索
{   
    int u; 
    visit(G, v); //訪問v號頂點
    visited[v] = true; //置標誌位爲”已訪問”
    u = FirstAdj(G, v); //取v的第一鄰接點序號u
    while (u >= 0) {  //當u存在時
        if (visited[u] == false) 
            DFS(G, u); //遞歸調用遍歷從u 出發的子圖
        u = NextAdj(G, v, u); //取v關於當前u的下一鄰接點序號 
     }
}  

除此之外,也可使用棧來實現:

public void BFS(Vnode[] G, int v) //對圖G從序號爲v的頂點出發,按BFS遍歷
{   
    int u; 
    Stack s; 
    ClearStack(s);   //置棧s爲空
    visit(G,v); 
    visited[v] = true; //訪問頂點, 置標誌爲“已訪問” 
    s.push(v);   //v進棧
    while (!s.isEmpty)  { //棧非空時
         v = s.pop(); //出棧
         u = FirstAdj(G, v); //取v的第一鄰接點序號
         while (u >= 0) {
             if (visited[u] == false) { //u未訪問過
                visit(G, u); visited[u] = true; 
                s.push(u.nextNode());//u的兄弟節點先入棧
                s.push(u);//u入棧
             }

         }
     }
} 

leetcode中的島嶼問題,基本上都是圖深度優先搜索的應用。

Leetcode島嶼問題彙總

200.島嶼數量

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

示例 1:

輸入:

11110
11010
11000
00000

輸出: 1


       示例 2:

輸入:

11000
11000
00100
00011

輸出: 3

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/number-of-islands
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

對於每一個爲陸地的島嶼,進行深度遍歷,將所有與其聯通的陸地全部訪問。代碼如下:

class Solution {
    public int numIslands(char[][] grid) {
        int res=0;
        for(int i=0;i<grid.length;i++){
            for(int j=0;j<grid[0].length;j++){
                if(grid[i][j]=='1'){
                    //g[i][j]=0;
                    res++;
                    deep(grid,i,j);
                }
            }
        }
        return res;
    }
    public void deep(char[][] g,int i,int j){
        if(i>=0 && i<g.length && j>=0 && j<g[0].length && g[i][j]=='1'){
            g[i][j]='0';
            deep(g,i+1,j);
            deep(g,i-1,j);
            deep(g,i,j+1);
            deep(g,i,j-1);

        }
    }
        
    
}

695.島嶼的最大面積

給定一個包含了一些 0 和 1的非空二維數組 grid , 一個 島嶼 是由四個方向 (水平或垂直) 的 1 (代表土地) 構成的組合。你可以假設二維矩陣的四個邊緣都被水包圍着。

找到給定的二維數組中最大的島嶼面積。(如果沒有島嶼,則返回面積爲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。

注意: 給定的矩陣grid 的長度和寬度都不超過 50。

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/max-area-of-island
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

代碼解決:

class Solution {
    public int maxAreaOfIsland(int[][] grid) {
        int max=0;
        for(int i=0;i<grid.length;i++){
            for(int j=0;j<grid[0].length;j++){
                if(grid[i][j]==1){
                    //g[i][j]=0;
                    int temp=0;
                    temp+=deep(grid,i,j);
                    max=Math.max(temp,max);
                }
            }
        }
        return max;
    }
    public int deep(int[][] g,int i,int j){
        if(i>=0 && i<g.length && j>=0 && j<g[0].length && g[i][j]==1){
            g[i][j]=0;
            int x=1+deep(g,i+1,j)+deep(g,i-1,j)+deep(g,i,j+1)+deep(g,i,j-1);
            return x;
        }else {
            return 0;
        }
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章