BFS经典套路题目,AC code如下:
class Solution {
public:
int openLock(vector<string>& deadends, string target) {
unordered_set<string>deadset(deadends.begin(),deadends.end());
unordered_set<string>visited;
visited.insert("0000");
queue<string> q;
q.push("0000");
int step=0;
while(!q.empty())
{
//广度优先遍历,处理同一层结点
int size = q.size();
for(int i = 0;i < size;i++)
{
string elem = q.front();
q.pop();
if(deadset.count(elem)) continue;
if(elem == target) return step;
visited.insert(elem);
for(int i= 0;i < 4;i++)
{
string up = plusone(elem,i);
if(!visited.count(up))
{
q.push(up);
visited.insert(up);
}
string down = minsone(elem,i);
if(!visited.count(down))
{
q.push(down);
visited.insert(down);
}
}
}
step += 1;
}
return -1;
}
private:
string plusone(string str,int i)//数字+1
{
str[i] = str[i]=='9'?'0':str[i]+1;
return str;
}
string minsone(string str,int i)//数字-1
{
str[i] = str[i]=='0'?'9':str[i]-1;
return str;
}
};
处于优化的目的,将deadset和visited合并,合并后的代码如下:
class Solution {
public:
int openLock(vector<string>& deadends, string target) {
unordered_set<string>visited(deadends.begin(),deadends.end());
queue<string> q;
q.push("0000");
int step=0;
while(!q.empty())
{
//广度优先遍历,处理同一层结点
int size = q.size();
for(int i = 0;i < size;i++)
{
string elem = q.front();
q.pop();
if(elem == target) return step;
if(visited.count(elem)) continue;
visited.insert(elem);
for(int i= 0;i < 4;i++)
{
string up = plusOne(elem,i);
if(!visited.count(up))
{
q.push(up);
}
string down = downOne(elem,i);
if(!visited.count(down))
{
q.push(down);
}
}
}
step += 1;
}
return -1;
}
private:
string plusOne(string str,int i)//数字+1
{
str[i] = str[i]=='9'?'0':str[i]+1;
return str;
}
string downOne(string str,int i)//数字-1
{
str[i] = str[i]=='0'?'9':str[i]-1;
return str;
}
};
性能上优化前反而快一些,非常直观的原因是合并之后visited元素个数较多,每次count时间增加,而优化前在第一个for循环前只是针对deadset做count,deadset不会增加,因此第一种方法空间复杂度和时间复杂度要优于优化后的算法。