如何快速写好bfs?

如何快速写好bfs?

为什么说是如何快速写好呢?
我认为于大多数人而言,懂得了基本的bfs模板,那么写好这个大概的框架肯定是不在话下,但就是有那么一段逻辑可能会格格不入。
那段逻辑就是扩散时候的各种操作逻辑。

  • 如何解决?
  1. 弄清扩散的目的是什么?扩散的目的是为了找到终点,如果该轮扩散都未找到终点,那么扩散就为你提供了后续的起点,也就是说扩散的最终目的还是为了找到终点。中间未找到终点的操作无非就是入队形成下一层结点,以及入visit防止走回头路。
  2. 把较为割裂的逻辑与主逻辑分离。这种方式运用于很多的大工程上,于一些复杂一点的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;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值