//对BFS的理解会更加通彻
class Solution {
public int openLock(String[] deadends, String target) {
//保存死亡数字.为什么要保存?
//因为可以使用contains方法判断, 而不需要for循环遍历数组
Set<String> deads = new HashSet<String>();
for(String s : deadends){
deads.add(s);
}
//记录已经走过的位置,防止走回头路。
Set<String> visited = new HashSet<>();
//接下来就是BFS搜索模板
Queue<String> q = new LinkedList<>();
int step = 0;
q.offer("0000");
visited.add("0000");
while(!q.isEmpty()){
int sz = q.size();
for(int i = 0; i < sz; i++){
String cur = q.poll();
if(deads.contains(cur)){
continue;
}
if(cur.equals(target)){
return step;
}
for(int j = 0; j < 4; j++){
String up = plusOne(cur, j);
if(!visited.contains(up)){
q.offer(up);
visited.add(up);
}
String down = minusOne(cur, j);
if (!visited.contains(down)) {
q.offer(down);
visited.add(down);
}
}
}
step++;
}
return -1;
}
//向上拨动一次
public String plusOne(String s, int j){
char[] ch = s.toCharArray();
if(ch[j] == '9'){
ch[j] = '0';
}else{
ch[j] += 1;
}
return new String(ch);
}
//向下拨动一次
public String minusOne(String s, int j) {
char[] ch = s.toCharArray();
if (ch[j] == '0'){
ch[j] = '9';
}else{
ch[j] -= 1;
}
return new String(ch);
}
}
题解过程:deadends = ["0201","0101","0102","1212","2002"], target = "0103"
0000 -> 0100
-> 0001
visted的作用就是不会再从0100转到0000了, 且0001也不会走到0000,因为这样重复走了
0000 -> 0100 -> 0101
-> 0100 -> 0109
-> 0001 -> 0101
-> 0001 -> 0002
此时有死亡的数字判断了
0000 -> 0100 -> 0101 (死亡数字跳过)
-> 0100 -> 0109
-> 0100 -> 0109 -> 0108
-> 0001 -> 0101 (死亡数字跳过)
-> 0001 -> 0002
-> 0001 -> 0002 -> 0102
-> 0001 -> 0002 -> 0902
......
以上是代表性的路径
最直观的就是 0000 -> 0100 -> 0109 -> 0108 -> 0107 -> 0106 -> 0105 -> 0104 -> 0103(0100 -> 0101路不通)
还有最简路径 0000 -> 0000 -> 0001 -> 0002 -> 0003 -> 0103
时间复杂度:O(N^2 * A^N + D)
空间复杂度:O(A^N + D)
其中A表示数字的个数,N表示状态的位数,D表示数组 deadends 的大小