打开轮盘锁问题(LeetCode)的分析总结及进一步提问
打开轮盘锁问题分析总结,及进一步提问:请给出一组最小步数下的号码序列组合
题目描述
你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字: ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’ 。每个拨轮可以自由旋转:例如把 ‘9’ 变为 ‘0’,‘0’ 变为 ‘9’ 。每次旋转都只能旋转一个拨轮的一位数字。
锁的初始数字为 ‘0000’ ,一个代表四个拨轮的数字的字符串。
列表 deadends 包含了一组死亡数字,一旦拨轮的数字和列表里的任何一个元素相同,这个锁将会被永久锁定,无法再被旋转。
字符串 target 代表可以解锁的数字,你需要给出解锁需要的最小旋转次数,如果无论如何不能解锁,返回 -1 。
进一步提问:请给出一组最小旋转次数下的号码序列组合
题目示例
示例1:
输入:deadends = [“0201”,“0101”,“0102”,“1212”,“2002”], target = “0202”
输出:6
解释:
可能的移动序列为 “0000” -> “1000” -> “1100” -> “1200” -> “1201” -> “1202” -> “0202”。
注意 “0000” -> “0001” -> “0002” -> “0102” -> “0202” 这样的序列是不能解锁的,
因为当拨动到 “0102” 时这个锁就会被锁定。
示例2:
输入: deadends = [“8888”], target = “0009”
输出:1
解释:把最后一位反向旋转一次即可 “0000” -> “0009”。
示例3:
输入: deadends = [“8887”,“8889”,“8878”,“8898”,“8788”,“8988”,“7888”,“9888”], target = “8888”
输出:-1
解释:无法旋转到目标数字且不被锁定。
求解
解决这个问题的一个常用方法是使用广度优先搜索(BFS)。广度优先搜索适合用于寻找最短路径的问题。在这种情况下,我们可以将每个可能的状态视为图中的一个节点,相邻状态视为图中的边。通过 BFS,我们可以找到从初始状态 “0000” 到目标状态的最短路径,同时避免所有的死亡数字状态。
要找出最少步数的密码状态组合,可以在广度优先搜索(BFS)过程中记录路径。在找到目标状态时,我们可以回溯路径来确定最少步数的密码状态组合。
详细步骤
1.初始化:
- 使用一个队列来进行 BFS,初始状态为 “0000”。
- 使用一个集合存储死亡数字,以便快速查找。
- 使用一个集合存储已访问的状态,以避免重复访问。
- 使用一个 Map 记录每个状态的前驱状态,以便在找到目标状态时回溯路径。
2.BFS 过程:
- 每次从队列中取出一个状态,检查它是否是目标状态。
- 对于当前状态的每一个位置,可以尝试增加或减少一位数字,生成新的状态。
- 如果生成的状态不是死亡数字且未被访问过,将其加入队列、已访问集合,并记录前驱状态。
- 继续这个过程,直到找到目标状态或者队列为空。
3.路径回溯:
- 当找到目标状态时,从目标状态开始,通过 Map 回溯到初始状态,生成路径。
代码实现
/*** 根据记录的密码序列父子关系,回溯所有密码序列* @param deadends 一组死亡数字* @param target 最末端的密码序列* @return 正序的密码序列数据(包括“0000”根节点)。* 当列表size不为0时,size-1 即为最小步数;* 当列表size为0时,表示:无论如何不能解锁。*/
public List<String> openLock(String[] deadends, String target) {Set<String> deadSet = new HashSet<>(Arrays.asList(deadends));if (deadSet.contains("0000")) {return Collections.emptyList();}//队列,实现BFS广度优先遍历Queue<String> queue = new LinkedList<>();//记录当前密码序列的上一个密码序列,即:记录父节点关系,便于回溯所有密码序列。Map<String, String> parent = new HashMap<>();//记录已经设置过的密码序列,防止重复判断陷入无限循环。Set<String> visited = new HashSet<>();queue.offer("0000");visited.add("0000");parent.put("0000", null);//根节点的父节点设置为空int steps = 0;while (!queue.isEmpty()) {int size = queue.size();//遍历每一层节点for (int i = 0; i < size; i++) {String current = queue.poll();if (current.equals(target)) {//最小步数产生,即最短路径或最小深度,回溯路径return constructPath(parent, target);}//根据当前密码序列,计算产生新的密码序列for (String next : getNextStates(current)) {if (!visited.contains(next) && !deadSet.contains(next)) {queue.offer(next);visited.add(next);parent.put(next, current);//记录父节点}}}steps++; //记录步数}return Collections.emptyList();
}/*** 根据记录的密码序列父子关系,回溯所有密码序列* @param parent 父子序列关系Map* @param target 最末端的密码序列* @return 正序的密码序列数据(包括“0000”根节点)*/
private List<String> constructPath(Map<String, String> parent, String target) {List<String> path = new LinkedList<>();for (String at = target; at != null; at = parent.get(at)) {path.add(at);}Collections.reverse(path);return path;
}/*** 获取当前密码序列的下一个状态的所有序列数据* @param current 当前密码序列* @return 所有的下一个状态序列*/
private List<String> getNextStates(String current) {List<String> nextStates = new ArrayList<>();char[] chars = current.toCharArray();for (int i = 0; i < 4; i++) {char original = chars[i];// 向前拨动密码轮盘chars[i] = original == '9' ? '0' : (char) (original + 1);nextStates.add(new String(chars));// 向后拨动密码轮盘chars[i] = original == '0' ? '9' : (char) (original - 1);nextStates.add(new String(chars));// 回复原来的号码chars[i] = original;}return nextStates;
}
测试代码
String[] deadends = {"0201", "0101", "0102", "1212", "2002"};String target = "0202";
// String[] deadends = {"8887", "8889", "8878", "8898", "8788", "8988","7888","9888"};
// String target = "8888";
// String[] deadends = {"8888"};
// String target = "0009";List<String> path = openLock(deadends, target);if (path.isEmpty()) {System.out.println("无论如何不能解锁!");} else {System.out.println("解锁序列:");for (String state : path) {System.out.println(state);}}
相关文章:
打开轮盘锁问题(LeetCode)的分析总结及进一步提问
打开轮盘锁问题分析总结,及进一步提问:请给出一组最小步数下的号码序列组合 题目描述 你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字: ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’ 。每个拨轮可以自由…...
python——joblib进行缓存记忆化-对计算结果缓存
问题场景 在前端多选框需要选取多个数据进行后端计算。 传入后端是多个数据包的对应路径。 这些数据包需要按一定顺序运行,通过一个Bag(path).get_start_time() 可以获得一个float时间值进行排序,但由于数据包的特性,这一操作很占用性能和时…...
Linux文件管理
系列文章目录 提示:仅用于个人学习,进行查漏补缺。 1.Linux介绍、目录结构、文件基本属性、Shell 2.Linux常用命令 3.Linux文件管理 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言1…...
《Unity3D网络游戏实战》学习与实践--制作一款大乱斗游戏
角色类 基类Base Human是基础的角色类,它处理“操控角色”和“同步角色”的一些共有功能;CtrlHuman类代表“操控角色”,它在BaseHuman类的基础上处理鼠标操控功能;SyncHuman类是“同步角色”类,它也继承自BaseHuman&…...
文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《考虑源-荷不确定性的省间电力现货市场潮流风险概率评估》
本专栏栏目提供文章与程序复现思路,具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…...
Pinterest 选择采用 TiDB
原文来源: https://tidb.net/blog/9f000c95 作者:Pinterest 公司高级软件工程师 Alberto Ordonez Pereira ;高级工程经理 Lianghong Xu 声明:本文转载于 https://medium.com/pinterest-engineering/tidb-adoption-…...
【Python】 如何用 Docker 打包一个 Python 脚本
这是我父亲 日记里的文字 这是他的生命 留下留下来的散文诗 几十年后 我看着泪流不止 可我的父亲已经 老得像一个影子 🎵 许飞《父亲写的散文诗》 如何用 Docker 打包一个 Python 脚本 Docker 是一个开源的容器化平台,允许开发者将…...
从“幕后”到“台前”:一文读懂API经济如何促进企业的创新与增长
API(Application Programming Interface,应用程序接口)指一组定义软件程序如何与其他组件、服务或系统交互的规范。在传统的IT语境中,API往往更多承担前后端对接或应用系统间内部集成渠道的作用。但在当今大数据与智能化的时代&am…...
解锁PDF新姿势:2024年PDF转图片工具精选
随着数字化办公的普及和文档处理需求的日益增长,PDF转图片工具已成为日常工作中不可或缺的一部分。这些工具不仅帮助用户轻松地将PDF文件转换为图片格式,还提供了丰富的编辑、转换和批量处理功能,极大地提高了工作效率。 1.福昕PDF转换大师&…...
Node.js(8)——Express的基本使用
监听GET请求 通过app.get()方法,可以监听客户端GET请求,具体语法: app.get(请求URL,function(req,res){处理函数}) 监听POST请求 语法: app.post(请求URL,function(req,res){处理函数}) 把内容响应给客户端 通过res.send()方法…...
Linux--应用层协议HTTP
HTTP协议 HTTP协议(HyperText Transfer Protocol,超文本传输协议)是互联网上应用最为广泛的一种网络协议,它基于TCP/IP通信协议来传送数据,规定了浏览器与服务器之间数据传输的规则,确保数据能够在网络源头…...
Flux:Midjourney的新图像模型挑战者
--->更多内容,请移步“鲁班秘笈”!!<--- Black Forest Labs是一家由前Stability.ai开发人员创立的AI初创公司,旨在为图像和视频创建尖端的生成式 AI 模型。这家初创公司声称,其第一个模型系列Flux.1为文本到图像…...
RabbitMQ高级特性 - 消费者消息确认机制
文章目录 RabbitMQ 消息确认机制背景消费者消息确认机制概述手动确认(RabbitMQ 原生 SDK)手动确认(Spring-AMQP 封装 RabbitMQ SDK)AcknowledgeMode.NONEAcknowledgeMode.AUTO(默认)AcknowledgeMode.MANUAL…...
PermX-htb
0x01 立足 信息收集 端口扫描 nmap -sSCV -Pn 10.10.11.23 正常开启22和80端口 访问web页面 并没有看到有攻击点 这个页面可先记录一会儿有需要的话可以尝试xss获取cookie 域名扫描 ffuf -w 1.txt -u http://permx.htb/ -H Host:FUZZ.permx.htb 这里用的ffuf扫描工具 扫出了…...
解密RCE漏洞:原理剖析、复现与代码审计实战
在网络安全领域,远程代码执行(RCE)漏洞因其严重性和破坏力而备受关注。RCE漏洞允许攻击者在目标系统上执行任意代码,从而掌控整个系统,带来极大的安全风险。理解RCE漏洞的工作原理,并掌握其复现与代码审计技…...
打造智能家居:用React、Node.js和WebSocket构建ESP32设备控制面板(代码说明)
一、项目概述 在物联网(IoT)时代,智能设备的远程控制变得越来越重要。本文介绍了一个构建智能设备控制面板的项目,允许用户通过 Web 应用来控制多个 ESP32 设备。用户可以通过该面板查看设备列表,实时了解设备状态&am…...
计网:从输入URL到网页显示期间发生了什么
1、URL包含的信息 我们输入的url中包含着一些信息: http:表示的此次我们使用的什么协议/www.baidu.com:表示的是我们想要访问的服务器名称,也就是域名dir3/home.html:表示我们所要访问的资源 2、通过DNS解析URL获得I…...
龚宇引以为傲的“爆款制造营”,爱奇艺怕是要爽约了
文:互联网江湖 作者:刘致呈 人们经常用人红戏不红,来形容毯星,综艺上咋咋呼呼,一提都知道,可问及代表作,不好意思,这个真没有。 今年的爱奇艺,貌似也迎来了这一宿命。 …...
org.springframework.web.client.HttpClientErrorException$NotFound异常
springCloud报错信息:org.springframework.web.client.HttpClientErrorException$NotFound: 404 null第一点: 第二点:没有httpclient工具类 注入RestTmeplate类时,改类需要RestController或ResponseBody...
在开关电源转换器中充分利用碳化硅器件的性能优势
在过去的几十年中,半导体行业已经采取了许多措施来改善基于硅 MOSFET (parasitic parameters),以满足开关转换器(开关电源)设计人员的需求。行业效率標準以及市场对效率技术需求的双重作用,导致了对于可用于构建更高效…...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...
MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...
