思路
每次只能操作一个锁盘转动一个数字,有4个锁,每个锁可以向上转或向下转,因此共有8中可能。⽐如说从 "0000" 开始, 转⼀次, 可以穷举出 "1000", "9000", "0100","0900"... 共 8 种密码。 然后, 再以这 8 种密码作为基础, 对每个密码再转⼀下, 穷举出所有可能......
基于以上思想,可以将全部结果构成一个八叉树,其中每一层标识操作一步后的全部可能,因此要求最少步数,就是求这个八叉树的最小深度,求树的深度最简单的方法就是BFS(广度优先搜索算法)。
好了,到这里整体的算法框架可以搭建出来,其次就是对于细节的处理:
1.何时返回:当旋转后的某个锁和密码相等时,直接返回此时八叉树的深度。
2.deadends如何处理:可以用一个数组记录deadends,每次旋转锁前先判断这个锁是否被记录在deadends数组中,如果存在就跳过本次操作。
3.如何防止走回头路:可以用另一个数组used记录已经验证过的数字组合,如果已经被验证过,则跳过。这种情况可以和2合并,用一个数组即可。
class Solution {
public:
int openLock(vector<string>& deadends, string target) {
unordered_set<string> used;
//将禁入加入到已进入列表
used.insert(deadends.begin(), deadends.end());
if(used.count("0000")) return -1;
int step = 0;
queue<string> myque;
string curlock = "0000";
myque.push(curlock);
used.insert(curlock);
while(!myque.empty())
{
int len = myque.size();
for(int i = 0; i < len; i++)
{
curlock = myque.front();
myque.pop();
if(!used.count(curlock)) continue;
if(curlock == target) return step;
for(int pos = 0; pos < 4; pos++)
{
string str1 = upNum(curlock, pos);
if(!used.count(str1))
{
myque.push(str1);
used.insert(str1);
}
string str2 = downNum(curlock, pos);
if(!used.count(str2))
{
myque.push(str2);
used.insert(str2);
}
}
}
step++;
}
return -1;
}
string upNum(string inlock, int pos)
{
string mylock = inlock;
if(mylock[pos] == '9')
mylock[pos] = '0';
else
mylock[pos]++;
return mylock;
}
string downNum(string inlock, int pos)
{
string mylock = inlock;
if(mylock[pos] == '0')
mylock[pos] = '9';
else
mylock[pos]--;
return mylock;
}
};
京公网安备 11010502036488号