[Leetcode 126] Word Ladder II

来源:互联网 发布:数据分析就业 编辑:程序博客网 时间:2024/06/11 03:14
  • Question
    Given two words (beginWord and endWord), and a dictionary’s word list, find all shortest transformation sequence(s) from beginWord to endWord, such that:

    Only one letter can be changed at a time
    Each transformed word must exist in the word list. Note that beginWord is not a transformed word.
    For example,

Given:beginWord = "hit"endWord = "cog"wordList = ["hot","dot","dog","lot","log","cog"]Return  [    ["hit","hot","dot","dog","cog"],    ["hit","hot","lot","log","cog"]  ]
  • 思路
    这个题是一个无向图查找所有的最短路径的题。
    我首先是想到了用深度搜索(DFS)去做。但是写出的代码只能通过 wordList 比较小的情况,wordList大的时候总是报 Time Limit Exceed错误。我在vs上调试时 发现原因是 递归调用层次太深,程序就死了。
    后面我采用空间换时间策略, 用BFS算法重写, 通过了。

    另外有一种思路是 BFS+DFS. 即先用BFS 把无向图变成有向图, 把每个节点的父节点和子节点保存下来,再用DFS 去查找最短路径,有兴趣的可以在网上找一下

-代码如下:

class Solution {public:/* compare() 是比较string a 和 b 有几个字母不同 */bool compare(string &a, string &b) {    int cnt = 0;    if (a.size() == b.size())        for (int i = 0; i < a.size(); ++i) {            if (a[i] != b[i]) {                ++cnt;                if (cnt > 1) break;            }        }    return cnt == 1;}/* build() 找出节点 word 的所有相邻节点,(即找出与 word 只有一个字符不同的所有 string), 保存到   set<string> 中*/set<string> build(string word, vector<string> &wordList) {    set<string> ret;    for (auto a : wordList) {        if (compare(a, word)) {            ret.insert(a);        }    }    return ret;}vector<vector<string>> findLadders(string beginWord, string endWord, vector<string> wordList) {    vector<vector<string>> ret;  // 返回    if ((find(wordList.begin(), wordList.end(), endWord)) == wordList.end()) return ret;    map<string, set<string>> str_set;       queue<string> s;    //记录从初始节点beginWord到当前节点的最短路径的长度    map<string, int> flash;  //记录从初始节点beginWord到当前节点的所有最短路径的,这些路径保存到set<vector<string>>中    map<string, set<vector<string>>> route;     //建立无向图,保存到 str_set 中    for (auto a : wordList) {        str_set[a] = build(a, wordList);        flash[a] = 0;    }    //将beginWord加入到图中,如果beginWord本身在图中也不会有影响    str_set[beginWord] = build(beginWord, wordList);    flash[beginWord] = 1;  //beginWord 到beginWord 路径长度为1,相应路径保存到route[beginWord]中    route[beginWord].insert({ beginWord });    s.push(beginWord);    while (!s.empty()) {        string val = s.front();        for (auto &a : str_set[val]) {        //遍历val的所有邻接点, flash[a] == 0 表示该节点该节点 第一次被访问,        //flash[a] >= (flash[val] + 1) 表示发现比当前找到的路径的长度相等或者更短的新路径,要更新            if (flash[a] == 0 || flash[a] >= (flash[val] + 1)) {                //找到更短的路径,则把先前保存的路径清除                if (flash[a] > flash[val] + 1){                    route[a].clear();                    flash[a] = flash[val] + 1;                 }                int temp = 1;                for (auto b : route[val]) {                    b.push_back(a);        //如果该路径已经保存在已有路径中,是重复访问,跳出,temp置0                    if (route[a].find(b) != route[a].end())                     {                        temp = 0;                        break;                    }                    route[a].insert(b);                }                //更新后的节点要重新加入到 队列中                if (temp)                    s.push(a);            }            if (a == endWord) break;        }        s.pop();    }    for (auto a : route[endWord])        ret.push_back(a);    return ret;}};
原创粉丝点击