双向BFS算法学习

news2025/1/12 18:59:47

双向BFS算法学习

推荐练习题
力扣“127”题:单词接龙
“752”题:打开轮盘锁
这里推荐一篇力扣题解
双向BFS
这里使用打开轮盘锁的题干进行举例:

你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字: ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’ 。每个拨轮可以自由旋转:例如把 ‘9’ 变为 ‘0’,‘0’ 变为 ‘9’ 。每次旋转都只能旋转一个拨轮的一位数字。

锁的初始数字为 ‘0000’ ,一个代表四个拨轮的数字的字符串。

列表 deadends 包含了一组死亡数字,一旦拨轮的数字和列表里的任何一个元素相同,这个锁将会被永久锁定,无法再被旋转。

字符串 target 代表可以解锁的数字,你需要给出解锁需要的最小旋转次数,如果无论如何不能解锁,返回 -1 。
在这里插入图片描述

分析

首先说明为什么使用双向BFS?
在这里我们可以把起点比做一个圆的圆心,我们使用BFS,就是对这个圆进行向外延伸,当延伸到目标点时,圆的面积就是时间复杂度,而我们采用双向BFS,就是从两
个点作为圆心,再进行延伸,当相交时,两个圆的面积小于只采用一个圆的面积(当目标点离起始点越远越明显)

这里我们与单向BFS的差别主要在下面几点:

  1. 这里有两个起始点,一个还是原来的起点0000,还有一个是我们的目标值,从这两个点开始发散的向四周发散的寻找,所以我们需要创建两个队列和两个保存已经遍历元素的哈希集
  2. 当一个队列的元素在另一个队列里面出现,这时说明两个点之间已经“打通”,找到了最短距离
  3. 这里注意我们尽量每次让两个队列平均的进行添加,这基于BFS的特性
  4. 这里结束循环的条件是两个队列都不为空,因为只要有一个位置空,就说明两点之间不能达到

代码

package Power;

import java.util.*;

public class doubleBFS {
    class Solution {
        String t, s;
        Set<String> set = new HashSet<>();
        public int openLock(String[] _ds, String _t) {
            s = "0000";
            t = _t;
            if (s.equals(t)) return 0;
            for (String d : _ds) set.add(d);
            if (set.contains(s)) return -1;
            int ans = bfs();
            return ans;
        }
        int bfs() {
            // d1 代表从起点 s 开始搜索(正向)
            // d2 代表从结尾 t 开始搜索(反向)
            Deque<String> d1 = new ArrayDeque<>(), d2 = new ArrayDeque<>();
            /*
             * m1 和 m2 分别记录两个方向出现的状态是经过多少次转换而来
             * e.g.
             * m1 = {"1000":1} 代表 "1000" 由 s="0000" 旋转 1 次而来
             * m2 = {"9999":3} 代表 "9999" 由 t="9996" 旋转 3 次而来
             */
            Map<String, Integer> m1 = new HashMap<>(), m2 = new HashMap<>();
            d1.addLast(s);
            m1.put(s, 0);
            d2.addLast(t);
            m2.put(t, 0);

            /*
             * 只有两个队列都不空,才有必要继续往下搜索
             * 如果其中一个队列空了,说明从某个方向搜到底都搜不到该方向的目标节点
             * e.g.
             * 例如,如果 d1 为空了,说明从 s 搜索到底都搜索不到 t,反向搜索也没必要进行了
             */
            while (!d1.isEmpty() && !d2.isEmpty()) {
                int t = -1;
                if (d1.size() <= d2.size()) {
                    t = update(d1, m1, m2);
                } else {
                    t = update(d2, m2, m1);
                }
                if (t != -1) return t;
            }
            return -1;
        }
        int update(Deque<String> deque, Map<String, Integer> cur, Map<String, Integer> other) {
            int m = deque.size();
            while (m-- > 0) {
                String poll = deque.pollFirst();
                char[] pcs = poll.toCharArray();
                int step = cur.get(poll);
                // 枚举替换哪个字符
                for (int i = 0; i < 4; i++) {
                    // 能「正向转」也能「反向转」,这里直接枚举偏移量 [-1,1] 然后跳过 0
                    for (int j = -1; j <= 1; j++) {
                        if (j == 0) continue;

                        // 求得替换字符串 str
                        // 这里使用的方法非常巧妙,把字符为0和9的特殊情况处理了
                        int origin = pcs[i] - '0';
                        // 取模处理9
                        int next = (origin + j) % 10;
                        // 如果为0.0-1为-1,进行处理,变成9
                        if (next == -1) next = 9;

                        char[] clone = pcs.clone();
                        clone[i] = (char)(next + '0');
                        String str = String.valueOf(clone);

                        // 如果死亡数组里面包含,就重新执行循环
                        if (set.contains(str)) continue;
                        // 如果已经遍历过,就重新执行循环
                        if (cur.containsKey(str)) continue;

                        // 如果在「另一方向」找到过,说明找到了最短路,否则加入队列
                        if (other.containsKey(str)) {
                            return step + 1 + other.get(str);
                        } else {
                            deque.addLast(str);
                            // 添加,更新步数
                            cur.put(str, step + 1);
                        }
                    }
                }
            }
            return -1;
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1654328.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于Nios-II的流水灯

基于Nios-II的流水灯 一、Qsys设计&#xff08;一&#xff09;新建项目&#xff08;二&#xff09;Platfrom Designer&#xff08;三&#xff09;设置时钟主频&#xff08;四&#xff09;添加Nios-II Processor并设置&#xff08;五&#xff09;添加JTAG并配置&#xff08;六&a…

2024年第七届人工智能和模式识别国际会议(AIPR 2024)即将召开!

2024年第七届人工智能和模式识别国际会议&#xff08;AIPR 2024)将于2024年9月20-22日在福建厦门市的华侨大学举行。探索AI边界&#xff0c;解锁识别新境界&#xff01;AIPR 2024旨在促进模式识别与机器学习, 计算机视觉与机器人视觉, 图像、语音、信号和视频处理等领域尖端成果…

ComfyUI中图像亮度/对比度/饱和度处理

用上面这个节点可以同时设置图片的亮度、对比度和饱和度。 【保姆级教程】一口气分享在ComfyUI中常用的30多种基本图像处理方式 更多好玩且实用AIGC工作流和节点 星球号&#xff1a;32767063 本期资料链接 往期学习资料 整理AI学习资料库

RabbitMQ的五种模式

一、简单模式 简单模式&#xff08;Simple&#xff09;&#xff1a;一个生产者&#xff0c;一个消费者 package com.qiangesoft.rabbitmq.mode.simple;import lombok.extern.slf4j.Slf4j; import org.springframework.amqp.rabbit.annotation.Queue; import org.springframe…

英语学习笔记4——Is this your ...?

Is this your …? 词汇 Vocabulary suit /sut/ n. 西装&#xff0c;正装 suit 的配套&#xff1a; shirt n. 衬衫tie n. 领带&#xff0c;领结belt n. 腰带trousers n. 裤子shoes n. 鞋子 school /skuːl/ n. 学校 所有学校 搭配&#xff1a;middle school 初中    hig…

分布式与一致性协议之ZAB协议(八)

ZAB协议 如何实现读操作 相比写操作&#xff0c;读操作的处理要简单很多&#xff0c;因为接收到度请求的节点只需要查询本地数据&#xff0c;然后响应数据给客户端就可以了。读操作的核心流程如图所示。 1.跟随者在FollowerRequestProcessor.processRequest()中接收到度请求…

JavaScript异步编程——04-同源和跨域

同源和跨域 同源 同源策略是浏览器的一种安全策略&#xff0c;所谓同源是指&#xff0c;域名&#xff0c;协议&#xff0c;端口完全相同。 跨域问题的解决方案 从我自己的网站访问别人网站的内容&#xff0c;就叫跨域。 出于安全性考虑&#xff0c;浏览器不允许ajax跨域获取…

mac监听 linux服务器性能可视化(Grafana+Promethus+Node_exporter)

Grafana和promethus(普罗米修斯)的安装和使用 监控系统的Prometheus类似于一个注册中心&#xff0c;我们可以只需要配置一个Prometheus,而在其他服务器&#xff0c;只需要安装node_exporter,它们的数据流转就是通过exporter采集数据信息&#xff0c;然后告诉prometheus它的位置…

redis分片java实践、redis哨兵机制实现、redis集群搭建

redis分片java实践 linux安装redishttps://mp.csdn.net/mp_blog/creation/editor/134864302复制redis.conf配置文件成redis1.conf、redis2.conf、redis3.conf 修改redis的端口信息和存pid文件的路径。存pid文件的路径只要不同就行了&#xff0c;没什么特别要求。 指定配置文件…

《编译原理》阅读笔记:p1-p3

《编译原理》学习第 1 天&#xff0c;p1-p3总结&#xff0c;总计 3 页。 一、技术总结 1.compiler(编译器) p1, But, before a program can be run, it first must be translated into a form in which it can be executed by a computer. The software systems that do thi…

【文章转载】ChatGPT 提示词十级技巧: 从新手到专家

学习了微博网友宝玉xp老师《ChatGPT 提示词十级技巧: 从新手到专家》 个人学习要点&#xff1a; 1、关于提示中避免使用否定句&#xff0c;播主说&#xff1a;“没有人能准确解释为什么&#xff0c;但大语言模型在你告诉它去做某事时&#xff0c;表现似乎比你让它不做某事时更…

C++语法|如何写出高效的C++代码(一)|对象使用过程中背后调用了哪些方法(构造和析构过程)?

文章目录 再探拷贝构造函数和重载复制运算符实例化新对象和赋值操作强转为类类型指针和引用时临时对象的构造和析构过程 考考你问题答案 再探拷贝构造函数和重载复制运算符 实例化新对象和赋值操作 首先我们写一个类&#xff0c;实现它的拷贝构造并重载赋值运算符。 class T…

算法学习006-瓷砖总数 广度优先算法BFS 中小学算法思维学习 信奥算法解析 c++实现

目录 C瓷砖总数 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 七、推荐资料 C瓷砖总数 一、题目要求 1、编程实现 在一个长方形房间&#xff0c;铺着不同颜色的的瓷砖&#xff0c;有红色和黑色&#…

流畅的python-学习笔记_序列修改+散列+切片

vector第一版 reprlib.repr用于选取有限长度较长变量 vector第二版切片 注意切片还有indices属性&#xff0c;它可以入参一个序列长度&#xff0c;根据此序列长度&#xff0c;转化不规矩的start stop stride&#xff0c; vector第三版动态存取属性 obj.attra时&#xff0c;先…

WordPress MasterStudy LMS插件 SQL注入漏洞复现(CVE-2024-1512)

0x01 产品简介 WordPress和WordPress plugin都是WordPress基金会的产品。WordPress是一套使用PHP语言开发的博客平台。该平台支持在PHP和MySQL的服务器上架设个人博客网站。WordPress plugin是一个应用插件。 0x02 漏洞概述 WordPress Plugin MasterStudy LMS 3.2.5 版本及之…

长难句打卡5.6

For H&M to offer a $5.95 knit miniskirt in all its 2,300-plus stores around the world, it must rely on low-wage overseas labor, order in volumes that strain natural resources, and use massive amounts of harmful chemicals. 翻译:H&M若要在其全球总共2…

JavaScript异步编程——05-回调函数

我们在前面的文章《JavaScript 基础&#xff1a;异步编程/单线程和异步》中讲过&#xff0c;Javascript 是⼀⻔单线程语⾔。早期我们解决异步场景时&#xff0c;⼤部分情况都是通过回调函数来进⾏。 &#xff08;如果你还不了解单线程和异步的概念&#xff0c;可以先去回顾上一…

多模态中的“单流模型”和“双流模型”

多模态预训练模型按照模型结构可以分为单流和双流两种结构。 单流是指图片和文本在embedding之后就融合在一起进入后续的transformer层。【先将信息fusion&#xff0c;然后再用一个model处理】双流是指文本和图片单独享有自己的transformer层&#xff0c;只在最后做轻量的融合…

添砖Java之路其二——基本数据类型,scanner,字符拼接。

目录 基本数据类型&#xff1a; ​编辑 Scanner: 字符拼接&#xff1a; 课后小题&#xff1a; 基本数据类型&#xff1a; 如图可见&#xff1a;Java里面有八种基本数据类型。 注意&#xff1a;在其中我们需要注意的是int默认整型数据&#xff0c;double是默认浮点型数据。因…

IP协议全解析:网络层通信的基石

⭐小白苦学IT的博客主页⭐ ⭐初学者必看&#xff1a;Linux操作系统入门⭐ ⭐代码仓库&#xff1a;Linux代码仓库⭐ ❤关注我一起讨论和学习Linux系统❤ 前言 在数字化时代的浪潮中&#xff0c;网络通信无处不在&#xff0c;它连接着世界的每一个角落&#xff0c;承载着信息的高…