遞歸,回溯,DFS,BFS的理解和模板


LeetCode 里面很大一部分題目都是屬於這個范圍,例如Path Sum用的就是遞歸+DFS,Path Sum2用的是遞歸+DFS+回溯

這里參考了一些網上寫得很不錯的文章,總結一下理解與模板

 

遞歸:就是出現這種情況的代碼: (或者說是用到了棧)

解答樹角度:在dfs遍歷一棵解答樹      

優點:結構簡潔

缺點:效率低,可能棧溢出

 

遞歸的一般結構:

 1 void f()  
 2 {  
 3      if(符合邊界條件)  
 4     {  
 5        ///////  
 6         return;  
 7     }  
 8       
 9      //某種形式的調用  
10      f();  
11 }  

 

回溯:遞歸的一種,或者說是通過遞歸這種代碼結構來實現回溯這個目的。回溯法可以被認為是一個有過剪枝的DFS過程。

解答樹角度:帶回溯的dfs遍歷一棵解答樹

回溯的一般結構:

 1 void dfs(int 當前狀態)  
 2     {  
 3           if(當前狀態為邊界狀態)  
 4           {  
 5             記錄或輸出  
 6             return;  
 7           }  
 8           for(i=0;i<n;i++)       //橫向遍歷解答樹所有子節點  
 9          {  
10                //擴展出一個子狀態。  
11                修改了全局變量  
12                if(子狀態滿足約束條件)  
13                 {  
14                   dfs(子狀態)  
15                }  
16                 恢復全局變量//回溯部分  
17             }  
18     }  

 

BFS和DFS是相似。

BFS(顯式用隊列)

DFS(隱式用棧)(即遞歸)

當然,對於DFS,用遞歸可能會造成棧溢出,所以也可以更改為顯示棧。

 

BFS:典型例題:P101 對於二叉樹的層次遍歷,P108對於圖的走迷宮最短路徑

 
1 將(起始)首節點加入隊列: q.push(head);  
2                      標記首節點已經被訪問:         isvisited[head]=true;  
3                     以下自動反應:                       while(!q.empty())  
4                                                                     {  
5                                                                           int temp=q.front();  
6                                                                            q.pop();  
7                                                                           訪問temp,並標記temp已被訪問過,將temp的子相關節點加入隊列  
8                                                                           q.push(temp相關節點);  
9                                                                     }  

 

DFS:典型例題:P107黑白圖像

格式:將所有節點遍歷一遍,在遍歷每個節點是,DFS的遍歷該節點相關的所有節點 

 
 1 void dfs(int x, int y)  
 2 {  
 3 if(!mat[x][y] || vis[x][y]) return;     // 曾經訪問過這個格子,或者當前格子是白色  
 4 vis[x][y] = 1;                          // 標記(x,y)已訪問過  
 5 dfs(x-1,y-1); dfs(x-1,y); dfs(x-1,y+1);  
 6 dfs(x-1,y);               dfs(x,y+1);  
 7 dfs(x+1,y-1); dfs(x+1,y); dfs(x+1,y+1); // 遞歸訪問周圍的八個格子  
 8 }  
 9 主循環:  
10 for(int i = 1; i <= n; i++)  
11 for(int j = 1; j <= n; j++)  
12 if(!vis[i][j] && mat[i][j])  
13 {  
14 count++;  
15 dfs(i,j);  
16 } // 找到沒有訪問過的黑格  

上述內容為轉載內容。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM