在我们上篇文章中,我们探讨了搜素技术4.1,4.2 递归与排列,子集生成和组合问题。我们再重温一遍:搜索技术是暴力法算法想法的具体实现。我们使用递归法将所有的可能性列出来,然后再用一些方法去掉我们不用的最后收获符合我们要求的内容。
全排列,子集,所有可能性,是这类题目的关键词。
接下来的搜索,是我们算法中基础中的基础: BFS和DFS
4.3.1 BFS和队列
深度优先搜索(Depth-first search, DFS) 和 广度优先算法(Breadth-first Search, BFS 是基本的暴力技术,常用于解决图,树的技术问题。
首先考虑算法思路。以老鼠走迷宫为例,这是DFS和BFS在现实中的模型。迷宫内部的错综复杂,老鼠从入口进入后怎么才能找到出口。有两种方法:
(1)一只老鼠走迷宫。它在每个路口都选择先走右边(当然,选择先走左边也可以),能走多远就走多远,直到碰壁无法继续往前走,然后回退一步,这一次走左边,接着继续往下走。用这个方法能走遍所有的路,而且不会重复(这里规定回退不算重复走)。这个思路就是DFS
(2)一群老鼠走迷宫。假设老鼠是无限多的,这群老鼠进去后,在每个路口派出部分老鼠探索所有没走过的路。走某条路的老鼠,如果碰壁无法前行,就停下;如果到达的路口已经有其他老鼠探索过了,也停下。很显然,所有的道路都会走到,而且不会重复。这个思路就是BFS。BFS看起来像“并行运算”,不过,因为程序是单机顺序运行的,所以可以把BFS看成是并行计算的模拟。
在具体编程的时候,一般用队列这种数据结构来具体实现BFS,甚至可以说“ BFS==队列 ”;对于DFS,也可以说“ DFS=递归 ”,因为用递归来实现DFS是最普遍的。DFS也可以用“栈”这种数据结构直接实现,栈和递归在算法思想上是一致的。
BFS in LeetCode
前言
之前写过的文章: Leetcode Graph(三)图的广度优先搜索 迷宫问题
Queue Basic Operation
queue<TreeNode*> curr_level;
curr_level.push(curr);
curr_level.pop();
BFS in Tree
Tree Level Order Traversal
102. Binary Tree Level Order Traversal 基础的基础
107. Binary Tree Level Order Traversal II 思路 = 基础 + 反转一下顺序。很简单,复习直接跳过
103. Binary Tree Zigzag Level Order Traversal 一样思路 reverse(vec.begin(),vec.end());
116. Populating Next Right Pointers in Each Node 第一次做,发现自己把问题想复杂了。思路:将同一层的nodes变为链表
// 将一层的nodes变为链表
// 本身nodes的next就是nullptr
Node* connect(Node* root) {
if(!root) return root;
queue<Node*> nodes;
nodes.push(root);
while(!nodes.empty()){
int size = nodes.size();
for(int i = 0; i < size; i++){
Node* curr = nodes.front();
nodes.pop();
if(i != size-1)
curr->next = nodes.front();
if(curr->left) nodes.push(curr->left);
if(curr->right) nodes.push(curr->right);
}
}
return root;
}
这道题还有一个根据完美二叉搜索树本身特征能做出来的解,很优雅,推荐
117. Populating Next Right Pointers in Each Node II 同理
199. Binary Tree Right Side View 同理
Tree 和 N-ary Tree思路是一致的。
Tree Depth
min depth: LeetCode 111 注意,不管是Graph 迷宫还是tree depth: min depth 是BFS, max depth是DFS(104 vs 111) 因为LeetCode 111 用 max depth做不出来。
BFS in Graph
LeetCode 1926, LeetCode 286
把思路掌握清楚基本上就完成了。BFS说到底就是暴力搜索,上下左右,然后剪枝,我只要*** 剩下丢掉。
其他
后续做题的时候发现自己和下面的题有点分不清。
对于 最快 能到某个点的题:用bfs。如果是有几种方法能到某个点的问题,用dynamic programming
这道题的分析请看另一篇文章