经典算法题之(知识补充)------ BFS和DFS的感性认识

1091. 二进制矩阵中的最短路径

问题描述及解答见上。

经典算法题之(六)------ 二维数组迷宫问题中列举了很多种情况,从条件放宽到可以任意走开始,就成了图的最短路径问题,一旦涉及到图的最短路径,则一定会用到DFS和BFS(能手写Dijkstra的话当我没说。。)。而这种两种思想在解决图的问题时也特别普遍,实际上,在二叉树的很多问题中也同样要用到这两种方法,特别是DFS,因为二叉树的三种遍历方法从本质上来说都是DFS,只是访问节点的时间点(在递归之前还是中间还是之后)不同。

所以,为了形象地认识DFS和BFS,特地做了两个GIF,当然为了简化问题,这里假设只能上下左右四个方向。

深度优先搜索DFS:

 

广度优先搜索BFS:

PS:引用这两个GIF请加上引用说明!!!真的花了很大的功夫才做好。。。

其实一目了然,左上角是起点,右下角是终点,白色为障碍物,黄色为可以走但还没有走的位置,蓝色为正在走的位置,灰蓝色为已经走的位置。

可以看到:

① 形象地去看,BFS像是浪花一圈圈向外扩散(那么障碍物就是鹅卵石),或者说像是瘟疫传染,下次访问的必然是本次访问的节点能够传染的节点(够得着),在代码实现中,本次访问的就是当前队列中的节点,下次访问(传染)的节点就是以当前节点作为传染源的其他节点——即下一轮放入队列中的节点。

可以想见,如果现在在图的中央放置一个“传染源”,那么BFS的遍历结果就像是在湖中心投了一颗石子,一直扩散到四周的岸边(当然,达到可能到岸的时间不一样)。

② 而DFS,更像是挖矿,认准一个方向一根筋地往“深处”挖,只要当前这个方向还挖的下去,就一直挖,如果这个方向挖不下去了,则在当前节点处换个方向挖,如果几个方向都挖过了,则回退。

一般来说,DFS在当前层递归时至少调用两次方法(因为至少是二叉树才用得到DFS),在上述可以自由走动的图时,一般要调用四次方法(四个方向),或者在更一般的图中,要遍历当前节点的所有“邻居”节点。用挖矿的角度看,这个遍历的顺序并不影响,如上图中,对于当前节点,可以顺时针“探测”,也可以“逆时针”探测,此时调用次序的定义更像是如何设计“探针”——无论怎么设计,只会影响访问的次序,并不会影响访问的最终结果——所有节点都访问且只访问了一次

 

综合BFS和DFS来看,BFS和DFS都达到了访问联通图中所有节点的效果,但BFS没有使用递归栈,没有回溯的过程(一路向前),故效率更高。

具体回到迷宫题目,为什么DFS和BFS最终的效果为什么没有差别,可以先局部再整体的方法分析。

局部来看,对于每个节点来说,访问本节点必然只能由本节点的邻居节点而来,也就是说,如果我遍历了你的所有邻居,并且取到你的最小距离,那么这个最小值就是访问到你的最短路径。

整体来看,BFS和DFS都访至少访问了所有节点一次,即对于任意一个节点,BFS和DFS必然都访问了你的所有邻居,并且,如果当前邻居更新了到你的最短路径——即通过这个邻居到达你的最短距离比通过之前的邻居到达你的最短距离更短,那么要将此节点重新放入队列中,在进行一次波纹扩散“。具体到代码实现上,就是访问当前节点时,尝试更新其邻居的dp值,如果邻居的dp值成功更新,则进而判断这个这个邻居(DFS采取递归方式,BFS是迭代方式——将这个邻居放入队列中)。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值