leetcode 752.打开转盘锁

管科研一新生首刷leetcode,本题思路来源leetcode官解,写此帖初衷是为了帮助自己更好的理解和“背诵”代码,方便后期复习,希望各位大佬多多指教!


题目描述

你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字: ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’ 。每个拨轮可以自由旋转:例如把 ‘9’ 变为 ‘0’,‘0’ 变为 ‘9’ 。每次旋转都只能旋转一个拨轮的一位数字。
锁的初始数字为 ‘0000’ ,一个代表四个拨轮的数字的字符串。
列表 deadends 包含了一组死亡数字,一旦拨轮的数字和列表里的任何一个元素相同,这个锁将会被永久锁定,无法再被旋转。
字符串 target 代表可以解锁的数字,你需要给出解锁需要的最小旋转次数,如果无论如何不能解锁,返回 -1 。

使用示例

输入:deadends = [“0201”,“0101”,“0102”,“1212”,“2002”], target = “0202”
输出:6
解释:
可能的移动序列为 “0000” -> “1000” -> “1100” -> “1200” -> “1201” -> “1202” -> “0202”。
注意 “0000” -> “0001” -> “0002” -> “0102” -> “0202” 这样的序列是不能解锁的,
因为当拨动到 “0102” 时这个锁就会被锁定。

解题思路

创建一个队列放入需要搜索的数字以及当前的搜索次数,再创建一个seen列表(set)存放已经访问过的数字,防止进行重复访问。
首先将“0000”以及times=0加入队列,进行广度优先搜索;先判断“0000”是否在deadends 中,若存在则直接返回-1;若不在,则对“0000”的各个位数分别进行一次拨动,例:“0001”,“0009”,“0010”,“0090”,“0100”,“0900”,“1000”,“9000”。依次判断上述数字是否在seen以及deadends中,若都不存在则加入队列,同时加入当前的times(每旋转一次times加一,在代码里就是一次for loop,但是不知道文字怎么表述);继续第二次旋转后的列表搜索,以此类推,若搜索过程中,某个变换的字符等于target,则返回当前times,当搜索完成未找到相应字符时,返回-1。

python代码实现

class Solution:
    def openLock(self, deadends: List[str], target: str) -> int:
        if target == "0000":
            return 0
        dead = set(deadends)
        if "0000" in dead:
            return -1
        
        def prev(n):
            return '9' if n == '0' else str(int(n) - 1)

        def succ(n):
            return '0' if n == '9' else str(int(n) + 1)

        def get(status):
            s = list(status)
            for i in range(4):
                num = s[i]
                s[i] = prev(num)
                yield "".join(s)
                s[i] = succ(num)
                yield "".join(s)
                s[i] = num      # 你这步是要让s继续变成[0,0,0,0]没有这个你i = 1 进行loop的时候就是[1,0,0,0]了,但是每次只能移动一个的嘛!
            
        q = collections.deque([('0000',0)])
        seen = {'0000'}
        while q:
            status,step = q.popleft()
            for next_status in get(status):
                if next_status not in seen and next_status not in dead:
                    if next_status == target:
                        return step + 1
                    q.append((next_status,step+1))
                    seen.add(next_status)
        return -1

yield生成器的使用方法

  • yield只能在函数中使用,其作用与return相似?
  • yield返回的生成器使用for loop或者next()对元素进行遍历
参考资料:

https://zhuanlan.zhihu.com/p/268605982

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学不明白属于是

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值