[LeetCode] 752. Open the Lock 开锁
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.
Example 1:
Input: deadends = ["0201","0101","0102","1212","2002"], target = "0202"
Output: 6
Explanation:
A sequence of valid moves would be "0000" -> "1000" -> "1100" -> "1200" -> "1201" -> "1202" -> "0202".
Note that a sequence like "0000" -> "0001" -> "0002" -> "0102" -> "0202" would be invalid,
because the wheels of the lock become stuck after the display becomes the dead end "0102".
Example 2:
Input: deadends = ["8888"], target = "0009"
Output: 1
Explanation:
We can turn the last wheel in reverse to move from "0000" -> "0009".
Example 3:
Input: deadends = ["8887","8889","8878","8898","8788","8988","7888","9888"], target = "8888"
Output: -1
Explanation:
We can't reach the target without getting stuck.
Example 4:
Input: deadends = ["0000"], target = "8888"
Output: -1
Note:
- The length of
deadendswill be in the range[1, 500]. targetwill not be in the listdeadends.- Every string in
deadendsand the stringtargetwill be a string of 4 digits from the 10,000 possibilities'0000'to'9999'.
Hint:
We can think of this problem as a shortest path problem on a graph: there are `10000` nodes (strings `'0000'` to `'9999'`), and there is an edge between two nodes if they differ in one digit, that digit differs by 1 (wrapping around, so `'0'` and `'9'` differ by 1), and if *both* nodes are not in `deadends`.
有一个可转动的四位数的密码锁,给一个目标值,还有一些锁死的情况,出现死锁的位置,就不能再动了,相当于迷宫中的障碍物。问最少多少步可以从初始的0000位置转动到给定的target位置。
可以把问题想成图的最短路径问题,有10000个节点(字符串‘0000'到'9999'),如果两个节点之间相差1并且不在锁死节点中,则它们之间有一个边。类似于迷宫遍历的问题,只不过相邻位置不再是上下左右四个位置,而是四位数字每个都加一减一,总共有八个相邻的位置。
解法:BFS
Java:
public static int openLock(String[] deadends, String target) {
Queue<String> q = new LinkedList<>();
Set<String> deads = new HashSet<>(Arrays.asList(deadends));
Set<String> visited = new HashSet<>();
int depth = 0;
String marker = "*";
q.addAll(Arrays.asList("0000", "*"));
while(!q.isEmpty()) {
String node = q.poll();
if(node.equals(target))
return depth;
if(visited.contains(node) || deads.contains(node))
continue;
if(node.equals(marker) && q.isEmpty())
return -1;
if(node.equals(marker)) {
q.add(marker);
depth += 1;
} else {
visited.add(node);
q.addAll(getSuccessors(node));
}
}
return depth;
}
private static List<String> getSuccessors(String str) {
List<String> res = new LinkedList<>();
for (int i = 0; i < str.length(); i++) {
res.add(str.substring(0, i) + (str.charAt(i) == '0' ? 9 : str.charAt(i) - '0' - 1) + str.substring(i+1));
res.add(str.substring(0, i) + (str.charAt(i) == '9' ? 0 : str.charAt(i) - '0' + 1) + str.substring(i+1));
}
return res;
}
Python:
Shortest path finding, when the weights are constant, as in this case = 1, BFS is the best way to go.
Best way to avoid TLE is by using deque and popleft() .
[Using list() and pop(0) is a linear operation in Python, resulting in TLE]
class Solution(object):
def openLock(self, deadends, target):
"""
:type deadends: List[str]
:type target: str
:rtype: int
"""
marker, depth = 'x', 0
visited, q, deadends = set(), deque(['0000', marker]), set(deadends) while q:
node = q.popleft()
if node == target:
return depth
if node in visited or node in deadends:
continue
if node == marker and not q:
return -1
if node == marker:
q.append(marker)
depth += 1
else:
visited.add(node)
q.extend(self.successors(node))
return -1 def successors(self, src):
res = []
for i, ch in enumerate(src):
num = int(ch)
res.append(src[:i] + str((num - 1) % 10) + src[i+1:])
res.append(src[:i] + str((num + 1) % 10) + src[i+1:])
return res
Python:
# Time: O(k * n^k + d), n is the number of alphabets,
# k is the length of target,
# d is the size of deadends
# Space: O(k * n^k + d)
class Solution(object):
def openLock(self, deadends, target):
"""
:type deadends: List[str]
:type target: str
:rtype: int
"""
dead = set(deadends)
q = ["0000"]
lookup = {"0000"}
depth = 0
while q:
next_q = []
for node in q:
if node == target: return depth
if node in dead: continue
for i in xrange(4):
n = int(node[i])
for d in (-1, 1):
nn = (n+d) % 10
neighbor = node[:i] + str(nn) + node[i+1:]
if neighbor not in lookup:
lookup.add(neighbor)
next_q.append(neighbor)
q, next_q = next_q, []
depth += 1
return -1
C++:
class Solution {
public:
int openLock(vector<string>& deadends, string target) {
unordered_set<string> deadlock(deadends.begin(), deadends.end());
if (deadlock.count("0000")) return -1;
int res = 0;
unordered_set<string> visited{{"0000"}};
queue<string> q{{"0000"}};
while (!q.empty()) {
++res;
for (int k = q.size(); k > 0; --k) {
auto t = q.front(); q.pop();
for (int i = 0; i < t.size(); ++i) {
for (int j = -1; j <= 1; ++j) {
if (j == 0) continue;
string str = t;
str[i] = ((t[i] - '0') + 10 + j) % 10 + '0';
if (str == target) return res;
if (!visited.count(str) && !deadlock.count(str)) q.push(str);
visited.insert(str);
}
}
}
}
return -1;
}
};
C++:
class Solution {
public:
int openLock(vector<string>& deadends, string target) {
unordered_set<string> deadlock(deadends.begin(), deadends.end());
if (deadlock.count("0000")) return -1;
int res = 0;
unordered_set<string> visited{{"0000"}};
queue<string> q{{"0000"}};
while (!q.empty()) {
++res;
for (int k = q.size(); k > 0; --k) {
auto t = q.front(); q.pop();
for (int i = 0; i < t.size(); ++i) {
char c = t[i];
string str1 = t.substr(0, i) + to_string(c == '9' ? 0 : c - '0' + 1) + t.substr(i + 1);
string str2 = t.substr(0, i) + to_string(c == '0' ? 9 : c - '0' - 1) + t.substr(i + 1);
if (str1 == target || str2 == target) return res;
if (!visited.count(str1) && !deadlock.count(str1)) q.push(str1);
if (!visited.count(str2) && !deadlock.count(str2)) q.push(str2);
visited.insert(str1);
visited.insert(str2);
}
}
}
return -1;
}
};
All LeetCode Questions List 题目汇总
[LeetCode] 752. Open the Lock 开锁的更多相关文章
- [LeetCode] Open the Lock 开锁
You have a lock in front of you with 4 circular wheels. Each wheel has 10 slots: '0', '1', '2', '3', ...
- LeetCode 752. Open the Lock
原题链接在这里:https://leetcode.com/problems/open-the-lock/ 题目: You have a lock in front of you with 4 circ ...
- java模拟开锁
java模拟开锁 service qq:928900200 Introduction to Computer Science II: CSCI142Fall 2014Lab #1Instructor: ...
- Java并发编程之Lock(同步锁、死锁)
这篇文章是接着我上一篇文章来的. 上一篇文章 同步锁 为什么需要同步锁? 首先,我们来看看这张图. 这是一个程序,多个对象进行抢票. package MovieDemo; public class T ...
- [C#基础]说说lock到底锁谁?
写在前面 最近一个月一直在弄文件传输组件,其中用到多线程的技术,但有的地方确实需要只能有一个线程来操作,如何才能保证只有一个线程呢?首先想到的就是锁的概念,最近在我们项目组中听的最多的也是锁谁,如何锁 ...
- Coarse-Grained lock 粗粒度锁
用一个锁Lock一组相关的对象 有时,需要按组来修改多个对象. 这样,在需要锁住其中一个的时候,必须连带地将其他的对象都上锁. 为每一个对象都加上一个锁是很繁琐的. 粗粒度锁是覆盖多个对象的单个锁. ...
- 4位开锁<dfs>
题意: 有一个四位密码的锁,每一位是1~9的密码,1跟9相连.并且相邻的连个密码位可以交换.每改变一位耗时1s,给出锁的当前状态和密码,求最少解锁时间. 思路: 用bfs枚举出所有相邻交换的情况,并记 ...
- Java 线程锁机制 -Synchronized Lock 互斥锁 读写锁
(1)synchronized 是互斥锁: (2)ReentrantLock 顾名思义 :可重入锁 (3)ReadWriteLock :读写锁 读写锁特点: a)多个读者可以同时进行读b)写者必须互斥 ...
- hihocoder 1075 : 开锁魔法III
描述 一日,崔克茜来到小马镇表演魔法. 其中有一个节目是开锁咒:舞台上有 n 个盒子,每个盒子中有一把钥匙,对于每个盒子而言有且仅有一把钥匙能打开它.初始时,崔克茜将会随机地选择 k 个盒子用魔法将它 ...
随机推荐
- github配置SSH proxy
在windows users 用户目录下生成config文件,如在C:\Users\your_user_name\.ssh 目录下,找到config文件,如果没有新建一个,写入如下内容: Host g ...
- idea 使用在java 包下的ftl、xml 文件编译问题
问题 使用ftl 时报错出现ftl 文件找不到,后发现idea未编译java 下的ftl文件 解决方法一 手动编译,复制ftl的文件夹在classes下应该在的地方 解决方法二 pom.xml中加入 ...
- HttpClient代码设置代理
由于对接faceBook接口,本地测试时候要设置代理才能调试. (http和https通用) public SSLContext createIgnoreVerifySSL() throws NoSu ...
- .NET Core项目修改project.json来引用其他目录下的源码等文件的办法 & 解决多框架时 project.json 与 app.config冲突的问题
作者: zyl910 一.缘由 项目规模大了后,经常会出现源码文件分布在不同目录的情况,但.NET Core项目默认只有项目目录下的源码文件,且不支持“Add As Link”方式引入文件.这时需要手 ...
- Python 进程共享数据(数据传输)实例
#coding:utf-8 ''' Created on 2017年11月22日 @author: li.liu ''' import multiprocessing from time import ...
- luoguP2768: 珍珠项链(矩阵乘法优化DP)
题意:有K种珍珠,每种N颗,求长度为1~N的项链,包含K种珍珠的项链种类数.N<=1e9, K<=30; 思路:矩阵快速幂,加个1累加前缀和即可. #include<bits/std ...
- 创建django项目完整实例
虚拟环境搭配 安装和配置 安装虚拟环境的命令: 1)sudo pip install virtualenv #安装虚拟环境 2)sudo pip install virtualenvwrapper # ...
- python的any()函数
any()函数的参数是一个可迭代对象,其中的一个元素有一个为真,则any()函数返回真,除非全部为假的时候才返回假. aaa=[,,,] print(any(aaa)) 返回:false
- 事件类型(onchange)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 使用vue+mintui 开发省市区功能
做移动端的都知道 经常会有省市区这种三级联动的功能 今天研究了一下午~ 1.准备工作 vue+mintui+省市区的json数据 下载地址:https://github.com/chzm/addres ...