打开转盘锁(LeetCode #752)
题目
你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有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" 时这个锁就会被锁定。
链接:https://leetcode-cn.com/problems/open-the-lock
解题思路
使用BFS框架进行求解
每次扩散时使用队列进行存储
每个密码扩散后有8可能的情况,遍历过程中需要判断是否为“死亡数字”
会走回头路。比如说我们从 "0000" 拨到 "1000",但是等从队列拿出 "1000" 时,还会拨出一个 "0000",这样的话会产生死循环
算法流程
用Set存放死亡数字和已经走过的密码将初始密码加入队列遍历队列
获取每一层队列的长度遍历该层队列
若为死亡数字,continue若为目标密码,返回depth排除以及走过的密码,将可能的密码加入队列 遍历下一层 没有找到,返回-1
代码
class Solution {
public int openLock(String
[] deadends
, String target
) {
Set
<String> deads
= new HashSet<>();
for(String s
: deadends
) deads
.add(s
);
Set
<String> visit
= new HashSet<>();
Queue
<String> queue
= new LinkedList<>();
String initPwd
= "0000";
queue
.offer(initPwd
);
visit
.add(initPwd
);
int depth
= 0;
while(!queue
.isEmpty()) {
int size
= queue
.size();
for(int i
= 0;i
< size
;i
++) {
String str
= queue
.poll();
if(deads
.contains(str
))
continue;
if(str
.equals(target
))
return depth
;
for(int j
= 0;j
< initPwd
.length();j
++) {
String upStr
= upPwd(str
, j
);
if(!visit
.contains(upStr
)) {
queue
.offer(upStr
);
visit
.add(upStr
);
}
String downStr
= downPwd(str
, j
);
if(!visit
.contains(downStr
)) {
queue
.offer(downStr
);
visit
.add(downStr
);
}
}
}
depth
++;
}
return -1;
}
public String
upPwd(String pwd
, int j
) {
char[] pwdArray
= pwd
.toCharArray();
if(pwdArray
[j
] == '9')
pwdArray
[j
] = '0';
else
pwdArray
[j
]++;
return String
.valueOf(pwdArray
);
}
public String
downPwd(String pwd
, int j
) {
char[] pwdArray
= pwd
.toCharArray();
if(pwdArray
[j
] == '0')
pwdArray
[j
] = '9';
else
pwdArray
[j
]--;
return String
.valueOf(pwdArray
);
}
}