题目描述
一个转盘有四位数字,范围是0~9 。并且扭动的时候非常自由,可以从0到9 也可以从9到0。 现在密码是 target “xxxx”,请问从"0000"开始至少需要多少次旋转可以得到target,其中必须避开 列表 deadends
输入输出样例
输入:deadends = ["0201","0101","0102","1212","2002"], target = "0202"
输出:6
解释:
可能的移动序列为 "0000" -> "1000" -> "1100" -> "1200" -> "1201" -> "1202" -> "0202"。
注意 "0000" -> "0001" -> "0002" -> "0102" -> "0202" 这样的序列是不能解锁的,
因为当拨动到 "0102" 时这个锁就会被锁定。
题解
使用广度优先搜索策略,将每一次的8种选择都添加进队列中
class Solution {
public int openLock(String[] deadends, String target) {
// 将deadend中的所有值都添加到 哈希表中
Set<String> dead = new HashSet<String>();
for(String str:deadends){
dead.add(str);
}
// 每个字符有两个旋转方向,一共可以旋转8个方向
Queue<String> queue = new LinkedList<String>();
// 存储已经出现过的情况
Set<String> seen = new HashSet<String>();
queue.add("0000");
seen.add("0000");
int count = 0;
while(!queue.isEmpty()){
int size = queue.size();
while(size-- > 0){
String str = queue.poll();
seen.add(str);
if(str.equals(target)) return count;
else if(!dead.contains(str)){
for(int i=0; i<4; i++){
for(int add = -1; add <= 1; add += 2){
// 得到转动后的值
int temp = (str.charAt(i) - '0' + add + 10) % 10;
String next = str.substring(0,i) + (""+temp) + str.substring(i+1);
if(!seen.contains(next)){
queue.offer(next);
seen.add(next);
}
}
}
}
}
count++;
}
return -1;
}
}