题目:

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

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

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

字符串 target 代表可以解锁的数字,你需要给出最小的旋转次数,如果无论如何不能解锁,返回 -1。

You have a lock in front of you with 4 circular wheels. Each wheel has 10 slots: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'. The wheels can rotate freely and wrap around: for example we can turn '9' to be '0', or '0' to be '9'. Each move consists of turning one wheel one slot.

The lock initially starts at '0000', a string representing the state of the 4 wheels.

You are given a list of deadends dead ends, meaning if the lock displays any of these codes, the wheels of the lock will stop turning and you will be unable to open it.

Given a target representing the value of the wheels that will unlock the lock, return the minimum total number of turns required to open the lock, or -1 if it is impossible.

示例 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
解释:
无法旋转到目标数字且不被锁定。

示例 4:

输入: deadends = ["0000"], target = "8888"
输出:-1

提示:

  1. 死亡列表 deadends 的长度范围为 [1, 500]
  2. 目标数字 target 不会在 deadends 之中。
  3. 每个 deadendstarget 中的字符串的数字会在 10,000 个可能的情况 '0000''9999' 中产生。

Note:

  1. The length of deadends will be in the range [1, 500].
  2. target will not be in the list deadends.
  3. Every string in deadends and the string target will be a string of 4 digits from the 10,000 possibilities '0000' to '9999'.

解题思路:

题目要求给出最小的旋转次数,应该就是用 BFS(广度优先搜索)解题了。初始字符串为 "0000" 那么第二步就是 "1000" "9000" "0100" "0900" "0010" "0090" "0001" "0009" 共八个字符串,也就是说每一步的字符串拨动密码扩展到下一步时可以得到八个新字符串。把它想象成图的形式:很明显相当于每个节点后有八个节点,用 BFS 每次走一个节点,直到达到目标节点,即是最短路径。

另外需要注意:每次到要判断节点是否为给出的死亡数字,并且把已遍历的节点也加入死亡数字以防止重复。这样只能将原数组形式的死亡数字转为哈希表以减少查找操作的复杂度。用队列暂存下一步需要遍历的节点。Java、python无法直接修改字符串里的字符.Java可先转换成 char 型数组,python可借助切片组装新字符串。

Java:

class Solution {
public int openLock(String[] deadends, String target) {
HashSet<String> dead_set = new HashSet<>(Arrays.asList(deadends));//死亡数字转为哈希表
if (dead_set.contains("0000")) return -1;//死亡数字如果含有初始节点,返回-1
Queue<String> queue = new LinkedList<>();//队列
queue.add("0000");//加入初始节点
int count = 0;//记录步数
while (!queue.isEmpty()) {//节点未访问完,队列内的节点不为空
int size = queue.size();//每一步节点数
while (size-- > 0) {
String tmp = queue.remove();//弹出头节点
if (target.equals(tmp)) return count;//如果与目标数相同,直接返回步数
char[] c = tmp.toCharArray();//转为数组
for (int j = 0; j < 4; j++) {//每次修改四位数字的一位
int i = c[j] - '0';//转为int型
c[j] = (char) ('0' + (i + 9) % 10);//数字-1。余数运算可防止节点为0、9时出现-1、10的情况
String s = new String(c);//得到新字符串
if (!dead_set.contains(s)) {//字符串不在死亡数字中时
queue.add(s);//添加到队列作为下一步需要遍历的节点
dead_set.add(s);//下一步必访问该节点,所以可先加入到死亡数字
}
c[j] = (char) ('0' + (i + 11) % 10);//数字+1
s = new String(c);
if (!dead_set.contains(s)) {
queue.add(s);
dead_set.add(s);
}
c[j] = (char) ('0' + i);
}
}
count++;
}
return -1;
}
}

Python:

class Solution:
def openLock(self, deadends: List[str], target: str) -> int:
#转成哈希表
dead_set = set(deadends)
if '0000' in dead_set: return -1
que = collections.deque(['0000'])
count = 0
while que:
for x in range(len(que)):
#从左取出头节点
tmp = que.popleft()
if tmp == target: return count
for i in range(4):
#分别存修改字符的左半部分字符串,待修改字符(转成int),右半部分字符
left, mid, right = tmp[:i], int(tmp[i]), tmp[i + 1:]
#j数字加一、减一拨动操作
for x in [-1, 1]:
s = left + str((mid + x) % 10) + right#切片拼接字符
if not s in dead_set:
dead_set.add(s)
que.append(s)
count += 1
return -1

关注微.信.公.众号:爱写Bug,一起学习吖

LeetCode 752:打开转盘锁 Open the Lock的更多相关文章

  1. Java实现 LeetCode 752 打开转盘锁(暴力)

    752. 打开转盘锁 你有一个带有四个圆形拨轮的转盘锁.每个拨轮都有10个数字: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' .每个拨轮可以自由旋 ...

  2. leetcode 752. 打开转盘锁

    地址 https://leetcode-cn.com/problems/open-the-lock/ 你有一个带有四个圆形拨轮的转盘锁.每个拨轮都有10个数字: '0', '1', '2', '3', ...

  3. Leetcode之广度优先搜索(BFS)专题-752. 打开转盘锁(Open the Lock)

    Leetcode之广度优先搜索(BFS)专题-752. 打开转盘锁(Open the Lock) BFS入门详解:Leetcode之广度优先搜索(BFS)专题-429. N叉树的层序遍历(N-ary ...

  4. [Swift]LeetCode752. 打开转盘锁 | Open the Lock

    You have a lock in front of you with 4 circular wheels. Each wheel has 10 slots: '0', '1', '2', '3', ...

  5. [LeetCode] 0752. Open the Lock 打开转盘锁

    题目 You have a lock in front of you with 4 circular wheels. Each wheel has 10 slots: '0', '1', '2', ' ...

  6. leetcode752. 打开转盘锁

    我们可以将 0000 到 9999 这 10000 状态看成图上的 10000 个节点,两个节点之间存在一条边,当且仅当这两个节点对应的状态只有 1 位不同,且不同的那位相差 1(包括 0 和 9 也 ...

  7. 第19/24周 锁升级(Lock Escalations)

    大家好,欢迎回到性能调优培训.上2个星期我们已经讨论了SQLServer里的悲观和乐观锁.今天我想谈下SQL Server里对于锁的一个特殊现象:所谓的锁升级(Lock Escalations).在我 ...

  8. ORACLE基础之oracle锁(oracle lock mode)详解

    ORACLE里锁有以下几种模式: 0:none 1:null 空 2:Row-S 行共享(RS):共享表锁,sub share  3:Row-X 行独占(RX):用于行的修改,sub exclusiv ...

  9. 同步锁Synchronized与Lock的区别?

    synchronized与Lock两者区别: 1:Lock是一个接口,而Synchronized是关键字. 2:Synchronized会自动释放锁,而Lock必须手动释放锁. 3:Lock可以让等待 ...

随机推荐

  1. WPF属性绑定实现双向变化

    WPF依赖项属性可以实现属性的绑定,成功绑定之后只要修改后台绑定的属性,即可UI同步自动更新绑定的值,无需手动刷新界面:同样,前台的值变化后,通过获取绑定的属性值也可获取UI变化后的值,实现双向变化的 ...

  2. kafka的主题与消费

    同一个消费者组不能同时消费同一个分区的数据 不同分区可以消费同一组不同消费者 同一个消费者可以同时消费多个topicA的数据 Topic和consumer依赖zookeeper,producer不依赖

  3. Z从壹开始前后端分离【 .NET Core2.0/3.0 +Vue2.0 】框架之四 || Swagger的使用 3.2

    本文梯子 本文3.0版本文章 前言 一.swagger的一般用法 0.设置swagger页面为首页——开发环境 1.设置默认直接首页访问 —— 生产环境 2.为接口添加注释 3.对 Model 也添加 ...

  4. 帝国cms提高网站网页打开速度的手段

    1.减少页面HTTP请求数量 2.使用CDN(Content Delivery Network)网络加速 3.添加文件过期或缓存头 4.服务器开启gzip压缩 5.css格式定义放置在文件头部 6.J ...

  5. Python爬取Boss直聘,帮你获取全国各类职业薪酬榜

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 王翔 清风Python PS:如有需要Python学习资料的小伙伴 ...

  6. 数据库-用户管理与pymysql

    mysql用户管理 !这是dba的活儿!,但是万一公司没有dba? mysql用户指的是什么? 我们每一次在操作前都需要指定账号和密码,这个账号就是mysql的用户; 为什么要管理? 一个公司不可能只 ...

  7. Zuul 1.x 的工作原理

    Zuul简介 Zuul在微服务架构中,可以作为提供动态路由,监控,弹性,安全等边缘服务的框架.在Netflix,被用作所有请求到达streaming application的前门.Zuul使用一系列不 ...

  8. C# Dictionary增加的方法

    1.简单的函数,实现Dictionary如果有就替换,没有就增加的功能. /// <summary>        /// Dictionary增加的方法        /// </ ...

  9. 一文解读ITIL (转)

    首先声明自己不是ITIL方面的专家,特别是具体的规范细节,后面论述如有不当,请指正.但我为什么会提起它?主要是因为它和运维(IT服务管理)相关性太大了.早起的运维完全就是以ITIL来蓝本构建的,在当时 ...

  10. 将vue2.9.6升级到vue3.0

    vue2.9.6没有ui界面可以用,直接使用yarn global add @cli没用,还是2.9.6版本 借鉴博客: https://juejin.im/post/5bf7d67c51882518 ...