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.
这道题是求单词衍变的最小步骤数,题目难度为Medium。
比较典型的广度优先搜索的题目,从初始单词开始进行一步衍变,如果新单词等于最终单词即可返回;如果新单词不等于最终单词且新单词在字典中,则将新单词存入队列(这里将新单词从字典中删除来避免回环并提高后续查找效率),之后再对队列中单词进行新的衍变直至找到最终单词或队列为空。具体代码:
class Solution {
public:
int ladderLength(string beginWord, string endWord, unordered_set<string>& wordList) {
queue<string> next;
int length = 1;
next.push(beginWord);
while(!next.empty()) {
int sz = next.size();
for(int i=0; i<sz; ++i) {
string cur = next.front();
next.pop();
if(cur == endWord) return length;
else {
for(int j=0; j<cur.size(); ++j) {
char c = cur[j];
for(char ch = 'a'; ch <= 'z'; ++ch) {
cur[j] = ch;
if(wordList.find(cur) != wordList.end()) {
next.push(cur);
wordList.erase(cur);
}
}
cur[j] = c;
}
}
}
++length;
}
return 0;
}
};
代码执行时间280ms左右,看了下别人的代码还有效率更高的方法,分享给大家。从两端两个方向上进行广度优先搜索,每次选择两端中单词数少的一方进行遍历,这样执行效率有了明显提升。具体代码:
class Solution {
public:
int ladderLength(string beginWord, string endWord, unordered_set<string>& wordList) {
unordered_set<string> head, tail;
int length = 2;
head.insert(beginWord);
tail.insert(endWord);
while(!head.empty() && !tail.empty()) {
if(head.size() > tail.size()) swap(head, tail);
unordered_set<string> next;
for(auto it = head.begin(); it != head.end(); ++it) {
string cur = *it;
for(int i=0; i<cur.size(); ++i) {
char c = cur[i];
for(char ch = 'a'; ch <= 'z'; ++ch) {
cur[i] = ch;
if(tail.find(cur) != tail.end()) return length;
if(wordList.find(cur) != wordList.end()) {
next.insert(cur);
wordList.erase(cur);
}
}
cur[i] = c;
}
}
++length;
swap(head, next);
}
return 0;
}
};
以上代码执行时间达到了79ms,不过始终没想明白为何选择单词少的一方进行遍历能够提高执行效率,明白的同学可以留言解下惑。