127. Word Ladder【力扣】

题意理解

给出一组单词,问从单词A到单词B的最短路径,相邻的单词只有一个字符不同。

问题分析

用图。BFS,BFS用队列。

思路1,如果从一个单词找它的下一个单词,遍历单词的每个字符,如果将当前字符换成a-z中的一个(最多26次),这样组成的新单词在列表中能找到,说明找到了。为了实现这个思路,将单词列表变换成无序集合,利用无序集合的find找到单词。

思路2,利用队列进行BFS思路,首先,起点如队列,然后,如果队列不空,出队列一个元素,对元素做操作,(中间可能终止遍历),遍历当前元素的相邻元素,依次入队列。

思路3,这题求最短距离长度,所以要对BFS进行改进,改进的方法是初始设置一个层次值为1,然后每次出队列元素时,不是每次出一个,而是用一个循环,每次出掉当前队列中所有的元素,(因为这些元素是一个层次上),当出完所有元素后,就可以增加层次,队列为空,或是找到相应的终单词时,层次数即为最短路径长度。

其他

队列的表示,入队列用push,出队列用pop,不是push_back, pop_front(遇到string会报错)

unordered_set,find元素时间复杂度是o(1).

参考:https://leetcode.com/problems/word-ladder/discuss/40707/C%2B%2B-BFS

链接

    int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
        unordered_set<string> dict(wordList.begin(), wordList.end());    //vector转化成hash表,便于查找
        queue<string> todo;
        todo.push(beginWord);  //队列用push,不是push_back
        int ladder = 1;    //设置层次初值
        while(!todo.empty())    //队列不空
        {
            int n = todo.size();    //取出当前层次的范围
            for(int i = 0; i < n; i++)  //只遍历当前层次的单词
            {
                string word = todo.front();    //出队列
                todo.pop();
            
                if(word == endWord)    //处理当前单词
                {
                    return ladder;
                }
                dict.erase(word);    //hash表更新(去掉处理过的单词)
                for(int j = 0; j < word.size(); j++) // 对每个字符进行变换
                {
                    char c = word[j];  
                    for(int k = 0; k < 26; k++)
                    {
                        word[j] = k + 'a';  //复用单词
                        if(dict.find(word) != dict.end())    //hash表查找单词
                        {
                            //cout << ladder << '\t' << word << endl;
                            todo.push(word);    //找到了就入队列
                        }
                    }
                    word[j] = c; //还原单词 
                }               
            }
            ladder++;    //本层次查询完毕,层次更新
        }
        return 0;
    }

 

点赞