题目
你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字: ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’ 。每个拨轮可以自由旋转:例如把 ‘9’ 变为 ‘0’,‘0’ 变为 ‘9’。每次旋转都只能旋转一个拨轮的一位数字。
锁的初始数字为 ‘0000’ ,一个代表四个拨轮的数字的字符串。
列表 deadends 包含了一组死亡数字,一旦拨轮的数字和列表里的任何一个元素相同,这个锁将会被永久锁定,无法再被旋转。
字符串 target 代表可以解锁的数字,你需要给出解锁需要的最小旋转次数,如果无论如何不能解锁,返回 -1 。
来源:力扣(LeetCode)
链接:752. 打开转盘锁
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
一、BFS
太懒了,直接改了改127. 单词接龙
class Solution {
public:
int openLock(vector<string>& deadends, string endWord) {
// 将vector转成unordered_set,提高查询速度
unordered_set<string> wordset(deadends.begin(), deadends.end());
// 如果endWord在wordSet出现,直接返回0
if(wordset.find(endWord)!=wordset.end()||wordset.find("0000")!=wordset.end())return -1;
if(endWord=="0000")return 0;
// 记录word是否访问过
unordered_map<string,int>umap;// <word, 查询到这个word路径长度>
queue<string>que;
que.push("0000");
umap["0000"]=0;
while(!que.empty())
{
string word=que.front();
que.pop();
int path=umap[word];
for(int i=0;i<word.size();i++)
{
int num=word[i]-'0';
int up=(num+1)%10;
int down=(num+10-1)%10;
string neword1 = word;
string neword2 = word;
neword1[i]=up+'0';
neword2[i]=down+'0';
if(endWord==neword1||endWord==neword2)return path+1;
// wordSet不出现newWord,并且newWord没有被访问过
if(wordset.find(neword1)==wordset.end()&&umap.find(neword1)==umap.end())
{
umap[neword1]=path+1;
que.push(neword1);
}
if(wordset.find(neword2)==wordset.end()&&umap.find(neword2)==umap.end())
{
umap[neword2]=path+1;
que.push(neword2);
}
}
}
return -1;
}
};
二、双向BFS
可以参考题解的解释,其实差不多
class Solution {
public:
int bfs(queue<string>& que, unordered_map<string, int>& umap1, unordered_map<string, int>& umap2, unordered_set<string>& wordset)
{
string word=que.front();
que.pop();
int path=umap1[word];
for(int i=0;i<4;i++)
{
int num=word[i]-'0';
int up=(num+1)%10;
int down=(num+10-1)%10;
string neword1 = word;
string neword2 = word;
neword1[i]=up+'0';
neword2[i]=down+'0';
/*if(wordset.find(neword1)!=wordset.end()||umap1.find(neword1)!=umap1.end()||wordset.find(neword2)!=wordset.end()||umap1.find(neword2)!=umap1.end())
{
continue
}*/
if(umap2.find(neword1)!=umap2.end())
{
return path+1+umap2[neword1];
}
if(umap2.find(neword2)!=umap2.end())
{
return path+1+umap2[neword2];
}
// wordSet不出现newWord,并且newWord没有被访问过
if(wordset.find(neword1)==wordset.end()&&umap1.find(neword1)==umap1.end())
{
if(umap2.find(neword1)!=umap2.end())
{
return path+1+umap2[neword1];
}
umap1[neword1]=path+1;
que.push(neword1);
}
if(wordset.find(neword2)==wordset.end()&&umap1.find(neword2)==umap1.end())
{
if(umap2.find(neword2)!=umap2.end())
{
return path+1+umap2[neword2];
}
umap1[neword2]=path+1;
que.push(neword2);
}
}
return -1;
}
int openLock(vector<string>& deadends, string endWord) {
// 将vector转成unordered_set,提高查询速度
unordered_set<string> wordset(deadends.begin(), deadends.end());
// 如果endWord在wordSet出现,直接返回0
if(wordset.find(endWord)!=wordset.end()||wordset.find("0000")!=wordset.end())return -1;
if(endWord=="0000")return 0;//注意
// 记录word是否访问过
unordered_map<string,int>mp1;// <word, 查询到这个word路径长度>
unordered_map<string,int>mp2;// <word, 查询到这个word路径长度>
queue<string>que1;
queue<string>que2;
que1.push("0000");
mp1["0000"]=0;
que2.push(endWord);
mp2[endWord]=0;
int res=-1;
while(!que1.empty()&&!que2.empty())
{
//选择一个容量更少的队列进行BFS搜索
if (que1.size() <= que2.size())
{
res = bfs(que1, mp1, mp2, wordset);
}
else
{
res = bfs(que2, mp2, mp1, wordset);
}
if (res != -1) return res;
}
return -1;
}
};
总结
码一个BFS模板(这种还有点不太熟