题目
https://leetcode-cn.com/problems/open-the-lock/
BFS
锁的每一个数字都可以代表一个节点,锁一共右四个拨轮,每个拨轮有两个选择: 向上拨,这样每个节点与8个节点相连,这就相当于一幅图,题目要求的是求最小的次数,因此可以利用广度优先搜索的特性。搜索过程中有一些点需要跳过: 1. 已经走过的的点,防止死循环; 2. deadends中的点。
class Solution {
public int openLock(String[] deadends, String target) {
Set<String> visited = new HashSet<>();
for (String dead : deadends) {
visited.add(dead);
}
LinkedList<String> queue = new LinkedList<>();
if (!visited.contains("0000")) {
queue.offer("0000");
visited.add("0000");
}
int step = 0;
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size ; i++) {
String cur = queue.poll();
if (cur.equals(target)) return step;
for (int j = 0; j < 4; j++) {
String upNext = up(cur, j);
String downNext = down(cur, j);
if (!visited.contains(upNext)) {
queue.offer(upNext);
visited.add(upNext);
}
if (!visited.contains(downNext)) {
queue.offer(downNext);
visited.add(downNext);
}
}
}
step++;
}
return -1;
}
private String up(String s, int i) {
char[] arr = s.toCharArray();
if (arr[i] == '9') {
arr[i] = '0';
} else {
arr[i] += 1;
}
return new String(arr);
}
private String down(String s, int i) {
char[] arr = s.toCharArray();
if (arr[i] == '0') {
arr[i] = '9';
} else {
arr[i] -= 1;
}
return new String(arr);
}
}
双向BFS
当知道起点和终点时,可以使用双向BFS进行优化。while 循环的最后交换 q1 和 q2 的内容,所以只要默认扩散 q1 就相当于轮流扩散 q1 和 q2。
class Solution {
public int openLock(String[] deadends, String target) {
Set<String> visited = new HashSet<>();
for (String d : deadends) {
visited.add(d);
}
Set<String> q1 = new HashSet<>();
Set<String> q2 = new HashSet<>();
q1.add("0000");
q2.add(target);
int step = 0;
while (!q1.isEmpty() && !q2.isEmpty()) {
Set<String> temp = new HashSet<>();
for (String cur : q1) {
if (visited.contains(cur))
continue;
if (q2.contains(cur))
return step;
visited.add(cur);
for (int j = 0; j < 4; j++) {
String upNext = up(cur, j);
if (!visited.contains(upNext))
temp.add(upNext);
String downNext = down(cur, j);
if (!visited.contains(downNext))
temp.add(downNext);
}
}
q1 = q2;
q2 = temp;
step++;
}
return -1;
}
private String up(String s, int i) {
char[] arr = s.toCharArray();
if (arr[i] == '9') {
arr[i] = '0';
} else {
arr[i] += 1;
}
return new String(arr);
}
private String down(String s, int i) {
char[] arr = s.toCharArray();
if (arr[i] == '0') {
arr[i] = '9';
} else {
arr[i] -= 1;
}
return new String(arr);
}
}