1. 题目
Given two words (beginWord and endWord), and a dictionary’s word list, find the length of shortest transformation sequence from beginWord to endWord, such that:
Only one letter can be changed at a time
Each intermediate word must exist in the word list
For example,
Given:
beginWord = “hit”
endWord = “cog”
wordList = [“hot”,”dot”,”dog”,”lot”,”log”]
As one shortest transformation is “hit” -> “hot” -> “dot” -> “dog” -> “cog”,
return its length 5.
Note:
Return 0 if there is no such transformation sequence.
All words have the same length.
All words contain only lowercase alphabetic characters.
2. 思路
注释部分提出来:
// 26叉树广度优先遍历,找到end,或者是树无法继续延伸
// 树的延伸是基于当前的字符串,每次变化一个字符[a-z]
// 如果新的字符串在wordlist里就加入候选和延伸队列里
// 由于是广度遍历,第一次找到的候选一定是最短路径的因此
// 可以将找到的候选从dict里删除,避免后续再找到的时候形成死循环
// 要计算是第几层,用一个空字符串来作为层之间的分隔符
这里最坑的地方是标准答案不是求的转移次数,而是求的转移链的链长度,也就是转移一次的情况,长度是2,其他类似的都是大了一。白白耗费了好多时间……
3. 代码
耗时:263ms
class Solution {
public:
// 26叉树广度优先遍历,找到end,或者是树无法继续延伸
// 树的延伸是基于当前的字符串,每次变化一个字符[a-z]
// 如果新的字符串在wordlist里就加入候选和延伸队列里
// 由于是广度遍历,第一次找到的候选一定是最短路径的因此
// 可以将找到的候选从dict里删除,避免后续再找到的时候形成死循环
// 要计算是第几层,用一个空字符串来作为层之间的分隔符
int ladderLength(string beginWord, string endWord, unordered_set<string>& wordList) {
if (beginWord == endWord) { return 0; }
if (beginWord.length() == 0) { return 0; }
wordList.erase(beginWord);
deque<string> q;
int step = 2;
q.push_back(beginWord);
q.push_back("");
while (!q.empty()) {
string s = q.front();
q.pop_front();
if (s == "") {
if (q.empty()) { return 0; }
q.push_back("");
step++;
continue;
}
//cout << "s=" << s << endl;
for (int w_i = 0; w_i < s.length(); w_i++) {
char ch = s[w_i];
for (char ch_i = 'a'; ch_i <= 'z'; ch_i++) {
if (ch_i == ch) { continue; }
s[w_i] = ch_i;
if (s == endWord) {
//cout << "find s=" << s << endl;
return step;
}
if (wordList.find(s) != wordList.end()) {
q.push_back(s);
wordList.erase(s);
//cout << "new s=" << s << endl;
}
s[w_i] = ch;
}
}
}
return 0;
}
};