递归,回溯,DFS,BFS的理解和模板

LeetCode 里面很大一部分题目都是属于这个范围,例如Path Sum用的就是递归+DFS,Path Sum2用的是递归+DFS+回溯


这里参考了一些网上写得很不错的文章,总结一下理解与模板

递归:就是出现这种情况的代码: (或者说是用到了栈)

解答树角度:在dfs遍历一棵解答树      

优点:结构简洁

缺点:效率低,可能栈溢出


递归的一般结构:

 
  1. void f()
  2. {
  3. if(符合边界条件)
  4. {
  5. ///////
  6. return;
  7. }
  8. //某种形式的调用
  9. f();
  10. }



回溯:递归的一种,或者说是通过递归这种代码结构来实现回溯这个目的。回溯法可以被认为是一个有过剪枝的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. } // 找到没有访问过的黑格

Ref:

http://hi.baidu.com/silverxinger/item/cdcd900ca34e988402ce1ba0

http://hi.baidu.com/lvhuyh/item/960c5b163c4d7cd539cb309b

http://www.cnblogs.com/HectorInsanE/archive/2010/11/09/1872656.html








全部评论

相关推荐

无敌虾孝子:喜欢爸爸还是喜欢妈妈
点赞 评论 收藏
分享
拿到一个offer了,貌似要996,大小周&nbsp;在纠结去不去。到现在还没有签三方,有点焦虑了
这我也不知道啊:慎重去鼎信,来我们学校宣讲在群里被疯狂质问为什么毁约应届生,hr还不承认。
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务