递归,回溯,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 } // 找到没有访问过的黑格  

上述内容为转载内容。

posted @ 2016-10-08 10:02  SarahLiu77  阅读(2396)  评论(0编辑  收藏  举报