给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则:
- 每次转换只能改变一个字母。
- 转换过程中的中间单词必须是字典中的单词。
说明:
- 如果不存在这样的转换序列,返回 0。
- 所有单词具有相同的长度。
- 所有单词只由小写字母组成。
- 字典中不存在重复的单词。
- 你可以假设 beginWord 和 endWord 是非空的,且二者不相同。
示例 1:
输入: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"] 输出: 5 解释: 一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog", 返回它的长度 5。
示例 2:
输入: beginWord = "hit" endWord = "cog" wordList = ["hot","dot","dog","lot","log"] 输出: 0 解释: endWord "cog" 不在字典中,所以无法进行转换。
思路:这道题是典型的DFS算法,首先看下题目中给的示例
start = "hit"
end = "cog"
dict = ["hot", "dot", "dog", "lot", "log"]
因为每次只能改变一个字符,如果我们从”hit“开始,只能改变和hit只有一个字符不同的字符串,比如 "hot"
。把这种思想抽象成图,那么“hot”是“hit”的邻接点。
思路是从start开始,每次访问它的邻接点,然后访问它的邻接点的邻接点... 这是典型的BFS解题模式。
为了简化问题, 把end放入dict中,只要在BFS遍历过程中发现了end,就直接返回结果. 我们维护一个int的变量 dist
,表示从开始节点到当前节点有过几次transform,然后在每次BFS后dist++,同时为了避免重复访问邻接点,每次访问一个word就从dict中删除该word。
参考代码:
class Solution {
public:
void addNextWord(string &beginWord, unordered_set<string>& wordList, queue<string> &q) {
wordList.erase(beginWord);
for (int i = 0; i < (int)beginWord.length(); i++) {
char letter = beginWord[i];
for (int j = 0; j < 26; j++) {
beginWord[i] = 'a' + j;
if (wordList.find(beginWord) != wordList.end()) {
q.push(beginWord);
wordList.erase(beginWord);
}
}
beginWord[i] = letter;
}
}
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
unordered_set<string> w_list;
for (auto s : wordList) w_list.insert(s);
if (w_list.find(endWord) == w_list.end()) return 0;
queue<string> q;
w_list.insert(endWord);
addNextWord(beginWord, w_list,q);
int dist = 2;
while (!q.empty()) {
for (int tmp = q.size(); tmp > 0; tmp--) {
auto top = q.front(); q.pop();
if (top == endWord) return dist;
addNextWord(top, w_list, q);
}
dist++;
}
return 0;
}
};