题目描述:
你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有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 = [“8887”,“8889”,“8878”,“8898”,“8788”,“8988”,“7888”,“9888”], target = “8888”
输出:-1
解释:
无法旋转到目标数字且不被锁定。
示例3
输入: deadends = [“0000”], target = “8888”
输出:-1
提示:
- 死亡列表
deadends
的长度范围为[1, 500]
。 - 目标数字
target
不会在deadends
之中。 - 每个
deadends
和target
中的字符串的数字会在 10,000 个可能的情况'0000'
到'9999'
中产生。
思路:
这道题是典型的bfs,直接附上代码,用代码中注释说明
代码如下:
class Solution(object):
def openLock(self, deadends, target):
"""
:type deadends: List[str]
:type target: str
:rtype: int
"""
from collections import deque
q = deque() #定义队列
visited = set() #定义一个记录已经访问的密码
deadends = set(deadends) # 变成集合,集合查询时间复杂度O(1)
# 如果“0000”在死亡数字,满足直接输出
if "0000" in deadends: return -1
# 先把”0000“加入相应的队列和在标记已访问
q.appendleft("0000")
visited.add("0000")
# 记录拨动一位密码次数
step = 0
while q:
# 队列长度
n = len(q)
while n:
# 队头出
s = q.pop()
# 判断是否死亡密码和是否为目标密码
if s in deadends:
n -= 1
continue
if s in target:
return step
# 改变不同为的数字
for i in range(4):
# 把这位数加1,减1 当然当为0,9要特殊考虑,
if s[i] == "0":
temp1 = s[:i] + "9" + s[i+1:]
temp2 = s[:i] + "1" + s[i+1:]
elif s[i] == "9":
temp1 = s[:i] + "8" + s[i+1:]
temp2 = s[:i] + "0" + s[i+1:]
else:
temp1 = s[:i] + str(int(s[i])-1) + s[i+1:]
temp2 = s[:i] + str(int(s[i])+1) + s[i+1:]
# print(temp1,temp2)
# 把得到的两个密码加入队列
if temp1 not in visited and temp1 not in deadends:
q.appendleft(temp1)
visited.add(temp1)
if temp2 not in visited and temp2 not in deadends:
q.appendleft(temp2)
visited.add(temp2)
# 队列个数减一
n -= 1
#步数加1
step += 1
return -1
测试代码:
a = Solution()
print(a.openLock(deadends = ["0201","0101","0102","1212","2002"], target = "0202"))
答案显示:6
正确!