LeetCode[126.Word Ladder II]题解 难度[hard]

**

题目

**
Given two words (beginWord and endWord), and a dictionary’s word list, find all shortest transformation sequence(s) from beginWord toendWord, such that:
1. Only one letter can be changed at a time
2. Each intermediate word must exist in the word list
For example,
Given:
beginWord = “hit”
endWord = “cog”
wordList = [“hot”,”dot”,”dog”,”lot”,”log”]
本题是127word ladder加强版,大致意思就是要找出两个单词的所有最短词梯并输出。

**

算法

**
算法思路与第一版word ladder大致相同(详细参考第一版word ladder题解接:http://blog.csdn.net/cs_linyf/article/details/52450201),使用BFS,不同之处是这题要输出最短路径。所以要把变化经过的单词都记录下来,这里可以使用一个map来记录每个单词的前驱是什么,由于路径有多条,前驱不是唯一的,所以映射到一个vector中。当找到目标单词时,词梯中所有单词的前驱都已经记录在这映射中,这里可以用一个递归来还原最短路径。
实现如下:

class Solution {
public:
    vector<vector<string> > findLadders(string beginWord, string endWord, unordered_set<string> &wordList) {
        vector<string> current,next;  //BFS时当前层和下一层
        current.push_back(beginWord); 
        bool exist = false; 
        while(!current.empty()){    
            int n = current.size();
            for(int i=0; i<n; ++i)      //把当前层的所有单词从字典里删除 
                wordList.erase(current[i]);  
            for(int i=0; i<n; ++i){     //遍历当前层 
                string word = current[i];
                int word_len = word.size();
                for(int j=0; j<word_len; ++j){  
                    string temp = word;
                    for(char x='a'; x<='z'; ++x){
                        if(temp[j]!=x){
                            temp[j] = x;                        
                            if(temp == endWord){
                                pre[temp].push_back(word);  //记录前驱 
                                exist = true;   
                                continue; 
                            }   
                            else if(wordList.find(temp)!=wordList.end()){
                                pre[temp].push_back(word);                          
                                bool put = true;
                                if(pre[temp].size()!=1) put = false;     //防止一个单词在next里出现几次                         
                                if(put) next.push_back(temp);
                            }                       
                        }
                    }
                }
            }
            if(exist) break;    //遍历完当层,最短路已经找完 
            current.clear();
            current = next;
            next.clear();
        }   
        if(exist)   generatePaths(beginWord,endWord);

        return paths;
    }
private:
    vector<vector<string> > paths;
    vector<string> temp_path;
    unordered_map<string, vector<string> > pre; //记录单词的前驱 
    void generatePaths(string beginWord,string endWord){
        //用递归找回所有路径 
        temp_path.push_back(endWord);   
        if(beginWord == endWord){
            int n = temp_path.size();
            vector<string> tmp;
            for(int i=n-1; i>=0; --i)
                tmp.push_back(temp_path[i]);
            paths.push_back(tmp);   
        }
        else{
            int n = pre[endWord].size();
            for(int i=0; i<n; ++i)
                generatePaths(beginWord,pre[endWord][i]);
        }
        temp_path.pop_back();
    }
};

可以AC,耗时343ms
这里写图片描述

思考:
若本题使用双向BFS应该怎样实现呢?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值