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 transformed word must exist in the word list. Note that beginWord is not a transformed word.
Note:
- Return 0 if there is no such transformation sequence.
- All words have the same length.
- All words contain only lowercase alphabetic characters.
- You may assume no duplicates in the word list.
- You may assume beginWord and endWord are non-empty and are not the same.
Example 1:
Input: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"] Output: 5 Explanation: As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog", return its length 5.
Example 2:
Input: beginWord = "hit" endWord = "cog" wordList = ["hot","dot","dog","lot","log"] Output: 0 Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.
只相差一个字母的两个单词是可以相互转换的,将可以转换的单词表示成在图中有连接边的节点,将beginWord到endWord的判断转化为判断从beginWord到endWord是否存在一条可行的路径。题目问的是最少转换的次数,等同于求图上起点到终点的最短路径,用BFS搜索就可以了。
一开始从某个节点找和它邻接的节点,我用的方法是用这个节点和所有其他节点进行判断是否为可转换的,这样做下来时间用的比较长,不太理想。后来参考别人的做法,由于一共只有26个字母,因此可以产生所有可能的可转换的单词,然后检查这个单词是否在给定的单词集合内。频繁的查询怎么提高效率?set。最后做下来跑test cases基本上速度减少了一半。后来做了一些其他BFS的题目,总结出一点经验,在用BFS的时候通常需要合理的设置辅助的set或map来加速查找,例如后来做的LC815 Bus Routes中设置了route和bus对应的、bus和route对应的两个map。BFS和set/map的辅助可以解决很多这类问题。
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
queue<string> q;
unordered_set<string> visited;
unordered_set<string> wordSet(wordList.begin(), wordList.end());
int pathLen = 1;
q.push(beginWord);
q.push("0");
while(!q.empty()) {
string qStr = q.front();
q.pop();
if (qStr == "0") {
pathLen += 1;
if (q.empty()) {
return 0;
}
q.push("0");
continue;
}
for (int i = 0; i < qStr.length(); i++) {
string word = qStr;
for (int j = 0; j <= 25; j++) {
word[i] = 'a' + j;
if (visited.find(word) == visited.end() && wordSet.find(word) != wordSet.end()) {
if (word == endWord) {
return pathLen + 1;
}
visited.insert(word);
q.push(word);
}
}
}
}
return pathLen + 1;
}