[Leetcode] 打开转盘锁(BFS求最短路径)
创始人
2024-05-24 16:22:09
0

题目链接:

https://leetcode.cn/problems/open-the-lock/

你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有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
解释:无法旋转到目标数字且不被锁定。

每一位可以往上或往下拨1,一共有四位,每个转盘状态的下一个状态最多对应(=2*4)8种情况

说明:要除去deadends中的组合,以及拨到过的组合

这是一个多叉树的问题(层数和拨动次数对应),可以使用层序遍历,即BFS来找最短路径

BFS求最短路径

维护一个队列,一层层加子节点,如果子节点中有目标就返回

细节问题:

如果起点在deadends,开局就挂,返回-1

如果目标就是起点,开局躺赢,返回0

class Solution:def openLock(self, deadends: List[str], target: str) -> int:#用一个字典存相邻的数neighbor = {}for i in range(10):neighbor[str(i)] = [str((i+9)%10),str((i+11)%10)]if "0000" in deadends:return -1if target == "0000":return 0q = ["0000"]level = 0#搜索过的节点vis = {"0000"}while q:n = len(q)for i in range(n):tmp = q.pop(0)L = list(tmp)children = []for j in range(4):num = L[j]L[j] = neighbor[num][0]children.append("".join(L))L[j] = neighbor[num][1]children.append("".join(L))L[j] = numfor child in children:if child == target:return level + 1if child not in deadends and child not in vis:vis.add(child)q.append(child)level += 1return -1

双向BFS求最短路径

适用场景:知道target是什么、正序和反序搜索行为一样(这样会比较简单)

也可以同时从起点和终点搜索,随着层级越多BFS维护的队列会越来越长,搜索的越来越广。从两端同时搜索,可以减少多叉树下半部分的搜索广度。本题知道起点和终点,反向搜索也是上或下拨一。

细节问题:

维护两个队列q和q2,交替搜索下一层,可以每搜索完一层交换两个队列(q,q2 = q2,q),即形式上一直搜索的是q,每次查看搜索出来的子节点是否在q2中(在则相遇了,返回步数)

class Solution:def openLock(self, deadends: List[str], target: str) -> int:neighbor = {}for i in range(10):neighbor[str(i)] = [str((i+9)%10),str((i+11)%10)]if "0000" in deadends:return -1if target == "0000":return 0q = ["0000"]level = 0#搜索过的节点vis = {"0000",target}q2 = [target]while q and q2:n = len(q)for i in range(n):tmp = q.pop(0)L = list(tmp)children = []for j in range(4):num = L[j]L[j] = neighbor[num][0]children.append("".join(L))L[j] = neighbor[num][1]children.append("".join(L))L[j] = numfor child in children:if child in q2:return level + 1if child not in deadends and child not in vis:vis.add(child)q.append(child)level += 1q,q2 = q2,qreturn -1

执行时间会快一些

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...