# [127. Word Ladder](https://leetcode.com/problems/word-ladder/) # 思路 词句阶梯: 给了我们一个单词字典,里面有一系列很相似的单词,然后给了一个起始单词和一个结束单词,每次变换只能改变一个单词,并且中间过程的单词都必须是单词字典中的单词,让我们求出最短的变化序列的长度。 要求最短路径长度,首先应该想到BFS。类似迷宫里面的最短路求法,迷宫每个点有上下左右四个方向可以走,而这里有26个字母,就是二十六个方向可以走,本质上没有区别。 另外由于需要频繁判断某个单词是否在字典中,所以我们用hashSet记录词典(代码中的`wordSet`)以快速进行判断。 ## 思路一 采用递归的BFS。首先我们用一个词语数组`beginWords`来记录开始的词语,初始化为一个元素`beginWord`,此外类似走迷宫的题目我们还需要一个`visited`来记录当前词语是否被访问过,这里我们用hashSet来定义`visited`。递归出口是`beginWords`为空。 ## 思路二、思路一改进 仔细分析我们可以发现了个hashSet`wordSet`和`visited`其实在功能上是有冗余的: 如果我们每访问一次`wordSet`里的词然后就把它从`wordSet`中去掉,这样不就不需要`visited`了吗?亲测会比思路一快很多。 ## 思路三 思路二的非递归版本。此时就不需要`beginWords`了而需要一个队列。 # C++ ## 思路一 ``` C++ class Solution { private: int BFS(vectorbeginWords, unordered_set&wordSet, unordered_set&visited, string &endWord){ vectornext_beginWords; string word; for(int i = 0; i < beginWords.size(); i++){ for(int j = 0; j < endWord.size(); j++){ word = beginWords[i]; if(word == endWord) return 1; for(char k = 'a'; k <= 'z'; k++){ word[j] = k; if(!wordSet.count(word) || visited.count(word)) continue; visited.insert(word); next_beginWords.push_back(word); } } } if(next_beginWords.empty()) return 0; // 递归出口 return BFS(next_beginWords, wordSet, visited, endWord) + 1; } public: int ladderLength(string beginWord, string endWord, vector& wordList) { unordered_setwordSet(wordList.begin(), wordList.end()); unordered_setvisited{beginWord}; if(wordSet.count(endWord) != 1) return 0; vectorbeginWords{beginWord}; return BFS(beginWords, wordSet, visited, endWord); } }; ``` ## 思路二 ``` C++ class Solution { private: int BFS(vectorbeginWords, unordered_set&wordSet, string &endWord){ vectornext_beginWords; string word; for(int i = 0; i < beginWords.size(); i++){ for(int j = 0; j < endWord.size(); j++){ word = beginWords[i]; if(word == endWord) return 1; char tmp_c = word[j]; for(char k = 'a'; k <= 'z'; k++){ word[j] = k; // tmp_c == k即新旧单词相同 if(!wordSet.count(word) || tmp_c == k) continue; wordSet.erase(word); next_beginWords.push_back(word); } } } if(next_beginWords.empty()) return 0; // 递归出口 return BFS(next_beginWords, wordSet, endWord) + 1; } public: int ladderLength(string beginWord, string endWord, vector& wordList) { unordered_setwordSet(wordList.begin(), wordList.end()); if(wordSet.count(endWord) != 1) return 0; vectorbeginWords{beginWord}; return BFS(beginWords, wordSet, endWord); } }; ``` ## 思路三 ``` C++ class Solution { public: int ladderLength(string beginWord, string endWord, vector& wordList) { unordered_set wordSet(wordList.begin(), wordList.end()); if (!wordSet.count(endWord)) return 0; queue q; q.push(beginWord); int res = 0; while (!q.empty()) { for (int k = q.size(); k > 0; --k) { string word = q.front(); q.pop(); if (word == endWord) return res + 1; for (int i = 0; i < word.size(); ++i) { string newWord = word; for (char k = 'a'; k <= 'z'; ++k) { newWord[i] = k; if (wordSet.count(newWord) && newWord != word) { q.push(newWord); wordSet.erase(newWord); } } } } ++res; } return 0; } }; ```