打开转盘锁
评论区大神代码:
public int openLock(String[] deadends, String target) {
Set<String> set = new HashSet<>(Arrays.asList(deadends));
//开始遍历的字符串是"0000",相当于根节点
String startStr = "0000";
if (set.contains(startStr))
return -1;
//创建队列
Queue<String> queue = new LinkedList<>();
//记录访问过的节点
Set<String> visited = new HashSet<>();
queue.offer(startStr);
visited.add(startStr);
//树的层数
int level = 0;
while (!queue.isEmpty()) {
//每层的子节点个数
int size = queue.size();
while (size-- > 0) {
//每个节点的值
String str = queue.poll();
//对于每个节点中的4个数字分别进行加1和减1,相当于创建8个子节点,这八个子节点
//可以类比二叉树的左右子节点
for (int i = 0; i < 4; i++) {
char ch = str.charAt(i);
//strAdd表示加1的结果,strSub表示减1的结果
String strAdd = str.substring(0, i) + (ch == '9' ? 0 : ch - '0' + 1) + str.substring(i + 1);
String strSub = str.substring(0, i) + (ch == '0' ? 9 : ch - '0' - 1) + str.substring(i + 1);
//如果找到直接返回
if (str.equals(target))
return level;
//不能包含死亡数字也不能包含访问过的字符串
if (!visited.contains(strAdd) && !set.contains(strAdd)) {
queue.offer(strAdd);
visited.add(strAdd);
}
if (!visited.contains(strSub) && !set.contains(strSub)) {
queue.offer(strSub);
visited.add(strSub);
}
}
}
//当前层访问完了,到下一层,层数要加1
level++;
}
return -1;
}
作者:数据结构和算法
链接:https://leetcode-cn.com/leetbook/read/queue-stack/kj48j/?discussion=5WQchG
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
我仿写了一遍,有个地方如果按我写的会超时,但是绝对是正确的,拿出来求网友解答,或者自己日后找到答案了就来解答:
class Solution {
public int openLock(String[] deadends, String target) {
Set<String> set = new HashSet<String>(Arrays.asList(deadends));
String startStr = "0000";
if(target.equals(startStr)){
return 0;
}
if(set.contains(startStr)){
return -1;
}
Queue<String> queue = new LinkedList<>();
Set<String> visited = new HashSet<>();
queue.offer(startStr);
visited.add(startStr);
int level = 0;
while(!queue.isEmpty()){
int size = queue.size();
while(size-->0){
String str = queue.poll();
if(str.equals(target)){
return level;
}
for(int i = 0;i<4;i++){
char ch = str.charAt(i);
String strAdd = str.substring(0,i)+(ch=='9'?0:ch-'0'+1)+str.substring(i+1);
String strSub = str.substring(0,i)+(ch=='0'?9:ch-'0'-1)+str.substring(i+1);
if(!visited.contains(strAdd)&&!set.contains(strAdd)){
visited.add(strAdd);
queue.offer(strAdd);
}
if(!visited.contains(strSub)&&!set.contains(strSub)){
visited.add(strSub);
queue.offer(strSub);
}
}
}
level++;
}
return -1;
}
}
其中
String strAdd = str.substring(0,i)+(ch=='9'?0:ch-'0'+1)+str.substring(i+1);
String strSub = str.substring(0,i)+(ch=='0'?9:ch-'0'-1)+str.substring(i+1);
若写成我的想法就会超时:
String strAdd = str.substring(0,i)+(ch=='9'?'0':ch+1)+str.substring(i+1);
String strSub = str.substring(0,i)+(ch=='0'?'9':ch-1)+str.substring(i+1);
哪里效率变低了呢?