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 } // 找到没有访问过的黑格
上述内容为转载内容。