[LeetCode] word ladder II

http://www.lintcode.com/zh-cn/problem/word-ladder-ii/#

给出两个单词(start和end)和一个字典,找出所有从start到end的最短转换序列

比如:

  1. 每次只能改变一个字母。
  2. 变换过程中的中间单词必须在字典中出现。

样例

给出数据如下:

start = "hit"

end = "cog"

dict = ["hot","dot","dog","lot","log"]

返回

[

    ["hit","hot","dot","dog","cog"],

    ["hit","hot","lot","log","cog"]

  ]

注意

  • 所有单词具有相同的长度。
  • 所有单词都只包含小写字母。
// Solution
//
//      1) Using BSF algorithm build a graph like below
//      2) Using DSF to parse the tree to the transformation path.
//
// For example:
//
//     start = "hit"
//     end = "cog"
//     dict = ["hot","dot","dog","lot","log","dit","hig", "dig"]
//
//                      +-----+
//        +-------------+ hit +--------------+
//        |             +--+--+              |
//        |                |                 |
//     +--v--+          +--v--+           +--v--+
//     | dit |    +-----+ hot +---+       | hig |
//     +--+--+    |     +-----+   |       +--+--+
//        |       |               |          |
//        |    +--v--+         +--v--+    +--v--+
//        +----> dot |         | lot |    | dig |
//             +--+--+         +--+--+    +--+--+
//                |               |          |
//             +--v--+         +--v--+       |
//        +----> dog |         | log |       |
//        |    +--+--+         +--+--+       |
//        |       |               |          |
//        |       |    +--v--+    |          |
//        |       +--->| cog |<-- +          |
//        |            +-----+               |
//        |                                  |
//        |                                  |
//        +----------------------------------+

class Solution {
public:
    vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
        unordered_map<string, unordered_set<string>> parent = BFS(start, end, dict);
        
        vector<string> path; path.push_back(start);
        vector<vector<string>> paths;
        DFS(start, end, parent, path, paths);
        return paths;
    }
    
private:
    unordered_map<string, unordered_set<string>> 
    BFS(const string &start, const string &end, const unordered_set<string> &dict) {
        
        /* 用于存储BFS形成的图结构 */
        unordered_map<string, unordered_set<string>> parent;
        
        /* 模拟图结构的每一层 */
        unordered_set<string> level[3];
        unordered_set<string> *previousLevel = &level[0];
        unordered_set<string> *currentLevel  = &level[1];
        unordered_set<string> *nextLevel     = &level[2];
        
        unordered_set<string> *p = NULL; // 用于交换指针用
        
        currentLevel->insert(start);
        
        /* BFS */
        
        bool flag = false;  // 当下一层插入的word中包含end,即退出BFS,因为所求为最短路径
        
        while (flag == false) {    // 还未到最后一层                              
            
            // 用于存储下一层的newWord(如果存在)
            nextLevel->clear();
            
            // 处理当前层
            for (const auto &word : *currentLevel) {             // 当前层中的每一个word
                for (int ix = 0; ix < word.size(); ix++) {       // 当前单词的每一个letter
                    string newWord = word;                                            
                    for (char c = 'a'; c <= 'z'; c++) {          // 对当前letter依次进行26个字母的替换
                        
                        newWord[ix] = c;
                        
                        // 不在词典中或者之前层已经出现过
                        if (dict.count(newWord) == 0 || previousLevel->count(newWord) == 1 || currentLevel->count(newWord) == 1) {
                            continue;
                        }
                        
                        if (newWord == end) {
                            flag = true;
                            parent[word].insert(newWord);
                            continue;
                        }
                        
                        parent[word].insert(newWord);
                        nextLevel->insert(newWord);
                    }
                }
            }
            
            if (nextLevel->empty()) {
                break;
            }
            
            p = currentLevel;
            currentLevel = nextLevel;
            nextLevel = previousLevel;
            previousLevel = p;
        }
        
        if (flag == false) {
            parent.clear();
        }
        
        return parent;
    }
    
    
    void DFS(const string &start, const string &end, 
             unordered_map<string, unordered_set<string>> &parent,
             vector<string> &path,
             vector<vector<string>> &paths) {
        if (parent.find(start) == parent.end()) {
            if (start == end) {
                paths.push_back(path);
            }
            return;
        }
        
        for (const auto &word : parent[start]) {
            path.push_back(word);
            DFS(word, end, parent, path, paths);
            path.pop_back();
        }
    }
};
posted @ 2015-05-21 19:24  Acjx  阅读(410)  评论(0编辑  收藏  举报