题目
一个密码锁由4个环形转轮组成,每个转轮由0~9这10个数字组成。每次可以上下拨动一个转轮,如可以将一个转轮从0拨到1,也可以从0拨到9。密码锁有若干死锁状态,一旦4个转轮被拨到某个死锁状态,这个锁就不可能打开。密码锁的状态可以用一个长度为4的字符串表示,字符串中的每个字符对应某个转轮上的数字。输入密码锁的密码和它的所有死锁状态,请问至少需要拨动转轮多少次才能从起始状态"0000"开始打开这个密码锁?如果锁不可能打开,则返回-1。例如,如果某个密码锁的密码是"0202",它的死锁状态列表是[“0102”,“0201”],那么至少需要拨动转轮6次才能打开这个密码锁,一个可行的开锁状态序列是"0000"→"1000"→"1100"→"1200"→"1201"→"1202"→"0202"。虽然序列"0000"→"0001"→"0002"→"0102"→"0202"更短,只需要拨动4次转轮,但它包含死锁状态"0102",因此这是一个无效的开锁序列。文章来源:https://www.toymoban.com/news/detail-780814.html
分析
对于这个问题而言,密码锁的每个状态都对应着图中的一个节点,如状态"0000"是一个节点,“0001"是另一个节点。如果转动某个转轮一次可以让密码锁从一个状态转移到另一个状态,那么这两个状态之间有一条边相连。例如,将状态"0000"分别向上或向下转动4个转轮中的一个,可以得到8个状态,即"0001”、“0009”、“0010”、“0090”、“0100”、“0900”、“1000"和"9000”,那么图中节点"0000"就有8条边分别和这8个状态对应的节点相连。文章来源地址https://www.toymoban.com/news/detail-780814.html
解
public class Test {
public static void main(String[] args) {
String[] deadends = {"0102", "0201"};
int result = openLock(deadends, "0202");
System.out.println(result);
}
public static int openLock(String[] deadends, String target) {
Set<String> dead = new HashSet<>(Arrays.asList(deadends));
Set<String> visited = new HashSet<>();
String init = "0000";
if (dead.contains(init) || dead.contains(target)) {
return -1;
}
Queue<String> queue1 = new LinkedList<>();
Queue<String> queue2 = new LinkedList<>();
int steps = 0;
queue1.offer(init);
visited.add(init);
while (!queue1.isEmpty()) {
String cur = queue1.remove();
if (cur.equals(target)) {
return steps;
}
List<String> nexts = getNeighbors(cur);
for (String next : nexts) {
if (!dead.contains(next) && !visited.contains(next)) {
queue2.add(next);
visited.add(next);
}
}
if (queue1.isEmpty()) {
steps++;
queue1 = queue2;
queue2 = new LinkedList<>();
}
}
return -1;
}
private static List<String> getNeighbors(String cur) {
List<String> nexts = new LinkedList<>();
for (int i = 0; i < cur.length(); i++) {
char ch = cur.charAt(i);
StringBuilder builder = new StringBuilder(cur);
char newCh = ch == '0' ? '9' : (char)(ch - 1);
builder.setCharAt(i, newCh);
nexts.add(builder.toString());
newCh = ch == '9' ? '0' : (char)(ch + 1);
builder.setCharAt(i, newCh);
nexts.add(builder.toString());
}
return nexts;
}
}
到了这里,关于面试算法109:开密码锁的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!