如何快速写好bfs?
Posted C_YCBX Py_YYDS
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何快速写好bfs?相关的知识,希望对你有一定的参考价值。
如何快速写好bfs?
为什么说是如何快速写好呢?
我认为于大多数人而言,懂得了基本的bfs模板,那么写好这个大概的框架肯定是不在话下,但就是有那么一段逻辑可能会格格不入。
那段逻辑就是扩散时候的各种操作逻辑。
- 如何解决?
- 弄清扩散的目的是什么?扩散的目的是为了找到终点,如果该轮扩散都未找到终点,那么扩散就为你提供了后续的起点,也就是说扩散的最终目的还是为了找到终点。中间未找到终点的操作无非就是入队形成下一层结点,以及入visit防止走回头路。
- 把较为割裂的逻辑与主逻辑分离。这种方式运用于很多的大工程上,于一些复杂一点的bfs,我们也应该用该方式分离逻辑,主逻辑是遍历队列进行下层扩散,而我们继续把扩散这一过程给分离,由上一点所说,将扩散过程分解为一个服务于寻找终点的函数,而它扩散后都会做完两个操作:入队(对于双向bfs则是入Set)和入visit。
例题练手
题目
双向bfs主逻辑
//双向bfs,两头轮流遍历
unordered_set<string>q1;
unordered_set<string>q2;
unordered_set<string>visit;
unordered_set<string>found;
int wordLen;
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
//构建结果能否被找到的图
for(string& t:wordList)found.insert(t);
//一旦endWord不存在其中,则无论如何都无答案
if(!found.count(endWord))return 0;
//初始化数据
q1.insert(beginWord);q2.insert(endWord);
visit.insert(beginWord);visit.insert(endWord);
int step = 1;
wordLen = beginWord.size();
while(!q1.empty()&&!q2.empty()){
unordered_set<string>temp;
//开始扩散寻求结果,直接封装成一个check函数,防止思维一时半会儿跟不上
for(auto s:q1){
//扩散找到了结果返回
if(check(s,temp))
return step+1;
}
//未找到结果,增加step,换q2遍历
step++;
q1 = q2;
q2 = temp;
}
return 0;
}
双向bfs扩散逻辑
//对每个单词位进行枚举,并对temp进行更新(如果是单向则是操作一个队列入队即可)
bool check(string& s,unordered_set<string>&temp){
for(int i=0;i<wordLen;i++){
char t = s[i];
for(char j='a';j<='z';j++){
if(t==j)continue;
s[i] = j;
if(found.count(s)){
//扩散找到答案
if(q2.count(s))
return true;
//未找到答案更新该层结果到temp
if(!visit.count(s)){
visit.insert(s);
temp.insert(s);
}
}
}
s[i] = t;
}
//此层扩散并未找到答案
return false;
}
整段代码提交后的效率
class Solution {
public:
//双向bfs,两头轮流遍历
unordered_set<string>q1;
unordered_set<string>q2;
unordered_set<string>visit;
unordered_set<string>found;
int wordLen;
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
//构建能否被找到的图
for(string& t:wordList)found.insert(t);
//一旦endWord不存在其中,则无论如何都无答案
if(!found.count(endWord))return 0;
//初始化数据
q1.insert(beginWord);q2.insert(endWord);
visit.insert(beginWord);visit.insert(endWord);
int step = 1;
wordLen = beginWord.size();
//开始双向bfs扩散
while(!q1.empty()&&!q2.empty()){
unordered_set<string>temp;
//开始扩散寻求结果,直接封装成一个check函数,防止思维一时半会儿跟不上
for(auto s:q1){
if(check(s,temp))
return step+1;
}
step++;
q1 = q2;
q2 = temp;
}
return 0;
}
private:
bool check(string& s,unordered_set<string>&temp){
for(int i=0;i<wordLen;i++){
char t = s[i];
for(char j='a';j<='z';j++){
if(t==j)continue;
s[i] = j;
if(found.count(s)){
//扩散找到答案
if(q2.count(s))
return true;
//未找到答案保存此层扩散结果(不含重复)
if(!visit.count(s)){
visit.insert(s);
temp.insert(s);
}
}
}
s[i] = t;
}
//此层扩散并未找到答案
return false;
}
};
以上是关于如何快速写好bfs?的主要内容,如果未能解决你的问题,请参考以下文章