[单向BFS][双向BFS]leetcode127:单词接龙(medium)

题目:
[单向BFS][双向BFS]leetcode127:单词接龙(medium)_第1张图片
题解:

解法1:单向BFS(普通BFS)

  • 1)排除边界条件:startWord或endWord为空或endWord不在wordList中或wordList为空。
  • 2)bfs的初始化工作:初始化步长,初始化queue,将startWord入队列,用vecotr来标记已经访问过的点。
  • 3)进行bfs:先将步长+1,然后确定每次bfs的长度size,寻找目标单词,然后出栈入栈等操作。

解法2:双向BFS

  • 1)由于单向bfs类似金字塔,越到底层,塔基越大(而众多塔基中只有一点end满足条件),而且其回溯路径也少。所以我们采用双向bfs,即既从begin->end遍历,又从end->begin遍历,当然每次我们都选用较短队列进行遍历,这样可减少用时。
  • 2)循环结束的条件是两个bfs碰头。每个单词遍历的方向,1由前向后遍历,2由后向前遍历,3两个bfs碰头。公式:0|1=1、0|2=2、1|2=3i&i=i、i&0=0

代码如下:

class Solution {
public:
    //题解1:普通bfs
    int ladderLength_1(string beginWord, string endWord, vector<string>& wordList) {
        //排除边界条件:1、字符串为空或字典表为空,2、endword不在字典表中
        if(wordList.empty()||beginWord.empty()||endWord.empty())return 0;
        if(find(wordList.begin(),wordList.end(),endWord)==wordList.end())return 0;
        
        //bfs的初始化工作
        int step=1;//计算步长          
        vector<int> visit(wordList.size());//标记wordList中的元素访问与否
        queue<string> q;
        q.push(beginWord);
        
        //开始进行bfs
        while(!q.empty())
        {
            step++;//在查找某个字符不一样的单词前,也将步长+1,所以我们找到目标单词时,直接返回步长
            int n=q.size();
            for(int i=0;i<n;++i)
            {
                string temp=q.front();q.pop();
                for(int j=0;j<wordList.size();++j)//在字典中寻找与temp的某个字符不一样的单词
                {
                    if(visit[j]==0)
                    {
                        int diff=0;
                        for(int k=0;k<temp.size();++k)
                            if(temp[k]!=wordList[j][k])diff++;
                        if(diff==1)//找到与temp某个字符不一样的单词
                        {
                            if(wordList[j]==endWord)return step;//找到目标单词直接返回步长
                            visit[j]=1;//标记下标为j的单词已访问
                            q.push(wordList[j]);
                        }
                    }
                }
            }
        }
        return 0;
    }
    
    //题解2:双向BFS
    int ladderLength_2(string beginWord, string endWord, vector<string>& wordList) 
    {
        //1、建立字典表,并利用hashmap去重
        unordered_map<string,int> freqs;
 	 for(const auto &word:wordList)freqs[word]=0;
        
        //2、排除极端情况:endWord不在字典表中
 	 if(freqs.count(endWord)==0) return 0;
        
        //3、bfs的初始化工作
 	 queue<string> q1({beginWord}), q2({endWord});//前向bfs,后向bfs
 	 int step=1;//步长
 	 for(freqs[beginWord]|=1,freqs[endWord]|=2; q1.size() && q2.size(); ++step){
  	 	bool first=q1.size()<q2.size();
   	 	queue<string> &q=first?q1:q2;//选择较小的队列进行遍历
   	 	int flag=first?1:2;//q1小由前向后遍历,q2小由后向前遍历
            
   		for(int size=q.size(); size--; q.pop()){
   			string &word=q.front();
    			if(freqs[word]==3) return step;//两个bfs碰头,返回步长
                
   			for(int i=0; i<word.length(); ++i){
     			for(char ch='a'; ch<='z'; ++ch){
      				string s=word;
      				if(s[i]==ch) continue;//跳出此次循环,继续寻找某个字符不一样的单词
      				s[i]=ch;//找到某个字符不一样的单词
                        	//表中没有该单词或者被访问过,跳出此次循环(1&1=1,2&2=2)
      				if(freqs.count(s)==0 || freqs[s]&flag) continue;
     				freqs[s]|=flag;//标记该单词被遍历过
      				q.push(s);
     				}
  	 		}
   		}
  	}
  return 0;        
  }
  
};
	

你可能感兴趣的:(leetcode刷题,#,BFS)