首页 > 其他分享 >BFS(广度优先搜索)优化技巧 — 双向遍历

BFS(广度优先搜索)优化技巧 — 双向遍历

时间:2024-06-13 18:29:38浏览次数:12  
标签:遍历 target cur BFS 双向 广度 string

BFS优化技巧 — 双向遍历

在之前我发过 动态规划框架动态规划的优化技巧 — 空间压缩,类似的,BFS框架 也有相应的优化技巧 双向遍历。从技巧的名字就可以看出,双向遍历指的就是从起点开始找终点的同时,也从终点开始找起点,一旦两个寻找过程出现交集,那么起点到终点的路径也就找出来了。

严谨一点表示:传统的 BFS 框架就是从起点开始向四周扩散,遇到终点时停止;而双向 BFS 则是从起点和终点同时开始扩散,当两边有交集的时候停止

同时扩散的话,效率肯定会更快一点,看下面两张图就会很明白了:

图的树形结构,【target】在最底层,按照传统BFS的遍历方式,需要从【start】开始,遍历所有节点,才能在最底层找到【target】,而双向遍历遍历树的一半时就出现了交集,也就是找到了最短距离。从这个例子是可以直观感受到,双向遍历是比传统传统单项遍历要好的。

但是,双向遍历的使用要有前提条件,也就是要提前知道【target】的位置,求【二叉树的最小深度】那道题就不适用,而【密码锁这道题】因为提前知道【target】的位置,所以可以使用双向遍历。

我在这给出使用双向遍历优化之后的代码:

 //将cur[j]向上拨一格
 string plusOne_(string cur, int j) {
     if (cur[j] == '9') cur[j] = '0';
     else cur[j] += 1;
     return cur;
 }
 ​
 //将cur[j]向下拨一格
 string minusOne_(string cur, int j) {
     if (cur[j] == '0') cur[j] = '9';
     else cur[j] -= 1;
     return cur;
 }
 ​
 //将问题抽象成图的问题,利用BFS算法解决问题
 int openLock(vector <string> &deadends, string target) {
     //需要先将死亡数字存储起来,为保证查找的时间复杂度为o(1),我们利用集合(哈希表)进行存储
     unordered_set <string> deads;
     for (string s: deadends) {
         deads.insert(s);
     }
     //记录穷举过的密码,防止走回头路
     unordered_set <string> q_start,q_target,visited;
     int step = 0;
     q_start.insert("0000");
     q_target.insert(target);
     //开始BFS遍历
     while (!q_start.empty() && !q_target.empty()) {
         //哈希表在遍历过程中不能修改,则新建一个哈希表temp存储扩散结果
         unordered_set <string> temp;
         
         //将q的所有节点进行扩散,先q_start,再q_target
         for(string s : q_start){
             if(deads.count(s) != 0) continue;
             if(q_target.count(s) != 0) return step; //说明出现了交集,直接返回结果
             visited.insert(s);
             
             //将每一个节点的未遍历节点加入temp中,作为下一层
             for(int j = 0; j < 4; j++){
                 string plusOne = plusOne_(s, j);
                 if(visited.count(plusOne) != 0) temp.insert(plusOne);   
                 string minusOne = minusOne_(s, j);
                 if(visited.count(plusOne) != 0) temp.insert(minusOne);  
             }
         }
         step++;
         q_start = q_target;
         q_target = temp;
     }
     //走到这里已经遍历完连通图的所有节点了,说明没有target
     return -1;
 }

这几天该准备我的期末考试了,所以每日分享的笔记篇幅会少一点,但是你们仍然可以借鉴与学习【手动狗头】。

标签:遍历,target,cur,BFS,双向,广度,string
From: https://blog.csdn.net/2302_76853832/article/details/139661523

相关文章

  • Future集合会等线程池执行完才开始遍历吗?
    先说结论:Future集合并不是等线程池执行完才开始遍历,而是线程池内的线程执行完一条Future集合就立即遍历一条在使用线程池的业务场景下,我们经常需要获取线程执行的返回值,此时我们需要Callable对象当做线程池参数并用List<Future>接收,然后遍历List<Future>获取我们想要的值。但是......
  • 力扣刷题记录: 1424. 对角线遍历Ⅱ
        本题是第182场周赛的Q3,LC竞赛分为1780。方法一.利用反对角线性质    在同一条反对角线上的元素的i+j值是相同的,同时,根据遍历的方式可知,i值越大的元素在同一条反对角线之中越先被遍历,i+j值越小的反对角线越早被遍历。考虑采用有序的map对i+j......
  • 使用foreach和stream遍历并修改List列表
    使用foreach和stream遍历并修改List列表1.使用foreachimportjava.util.ArrayList;importjava.util.HashMap;importjava.util.List;importjava.util.Map;importjava.util.stream.Collectors;publicclassTestList{publicstaticvoidmain(String[]args......
  • 程序猿大战Python——容器——字符串的遍历与常用的操作方法
    字符串的遍历使用for遍历字符串==目标:==掌握使用for语句遍历字符串。先来看看,for循环语法:for临时变量in序列: 满足条件时,执行的代码1 满足条件时,执行的代码2 ……[else:当for循环正常执行结束后,执行代码]例如,一起来完成:(1)定义一个字符串变量,内......
  • BFS实现图的点的层次-java
    加强对广度优先搜索的理解,其实就是主要的3个步骤,外加数组模拟单链表是基础,要搞懂。目录前言一、图中点的层次二、算法思路1.广度优先遍历 2.算法思路三、代码如下1.代码如下(示例):2.读入数据:3.代码运行结果:总结前言加强对广度优先搜索的理解,其实就是主要的3个步......
  • 树的4种遍历
    目录树的四种遍历方式的总结1.前序遍历(Pre-orderTraversal)2.中序遍历(In-orderTraversal)3.后序遍历(Post-orderTraversal)4.层序遍历(Level-orderTraversal或广度优先遍历,Breadth-FirstTraversal)以下是这四种遍历方式的C语言实现示例:1.定义二叉树节点2.前序遍......
  • KDY----BFS_宽度优先搜索习题
    题目由可达鸭提供,本篇够  字,阅读时注意休息和暂停。一、课时提交情(AC情况)T1、武士风度的牛  100/100(老师带着做的。)T2、抓住那头牛100/100T3、仙岛求药  100/100T4、TheCastle 0/100(时间不够了,就看了看题目。)二、目录T1、武士风度的牛T2、抓住那头牛T......
  • 代码随想录算法训练营第十四天|二叉树递归遍历、迭代遍历、统一迭代
    二叉树遍历二叉树主要有两种遍历方式:深度优先遍历:先往深走,遇到叶子节点再往回走。深度优先遍历又分:前序遍历(中、左、右)中序遍历(左、中、右)后序遍历(左、右、中)广度优先遍历:一层一层的去遍历。(后面讲)递归遍历递归三要素确定递归函数的参数和返回值:确定哪些参数是递......
  • Keil一键添加.c文件和头文件路径脚本--可遍历添加整个文件夹
    最近想移植个LVGL玩玩,发现文件实在是太多了,加的手疼都没搞完,实在不想搞了就去找脚本和工具,基本没找到一个。。。。。。主要是自己也懒得去研究写脚本,偶然搜到了一个博主写的脚本,原博客地址:https://blog.csdn.net/riyue2044/article/details/139424599但是有以下问题:1.这个脚本......
  • 144. 二叉树的前序遍历
    /***Definitionforabinarytreenode.*typeTreeNodestruct{*Valint*Left*TreeNode*Right*TreeNode*}*/funcpreorderTraversal(root*TreeNode)[]int{returnpre2(root)//vals:=[]int{}//pre1(root,&val......