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;
}
}
}