127. Word Ladder
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.
方法1: bfs
思路:
从beginWord开始,每次尝试将某个位置上的字母变成’a’ - 'z’中的一个,这些变化中,有哪些是在dictionary里面的,我们就有可能在该单词的基础上继续变化,向下搜索。此时要注意几点:
- 每次变化都要记录一个和始发点的距离,而第一次找到endword的单词,一定是距离最短的。这也是bfs的特点。
- 因此,我们需要将每次遇到的单词从dictionary中去掉遇到过的单词:第一是因为,没有必要再保留这个单词,下一次遇到时所经过的变化次数,一定更多。第二是因为,如果保留,会出现相邻两层之间死循环的情况。第三,自己和自己之间就会出现死循环。
Complexity
Time complexity: O(n ^26len),
class Solution {
public:
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
set<string> wordSet(wordList.begin(), wordList.end());
if (wordSet.empty() || !wordSet.count(endWord)) return 0;
queue<string> q;
q.push(beginWord);
int level = 1;
while (!q.empty()) {
int size = q.size();
for (int i = 0; i < size; i++) {
string top = q.front();
q.pop();
for (int j = 0; j < top.size(); j++) {
for (char change = 'a'; change < 'z'; change++) {
string next = top;
next[j] = change;
if (next == endWord) return level + 1;
if (wordSet.count(next)) {
q.push(next);
wordSet.erase(next);
}
}
}
}
level++;
}
return 0;
}
};
方法2: bidirectional bfs
huahua: https://zxi.mytechroad.com/blog/searching/127-word-ladder/
思路:
Complexity
Time complexity: O(n ^26len/2),
class Solution {
public:
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
set<string> wordSet(wordList.begin(), wordList.end());
if (!wordSet.count(endWord)) return 0;
queue<string> q1, q2;
unordered_map<string, int> visited1, visited2;
q1.push(beginWord);
q2.push(endWord);
visited1.insert({beginWord, 1});
visited2.insert({endWord, 1});
int level1 = 1, level2 = 1;
while (!q1.empty() && !q2.empty()) {
int size1 = q1.size();
for (int i = 0; i < size1; i++) {
string top = q1.front();
q1.pop();
for (int j = 0; j < top.size(); j++) {
for (char change = 'a'; change < 'z'; change++) {
string next = top;
next[j] = change;
if (visited2.count(next)) return level1 + visited2[next];
if (wordSet.count(next)) {
visited1.insert({next, level1 + 1});
q1.push(next);
wordSet.erase(next);
}
}
}
}
level1++;
int size2 = q2.size();
for (int i = 0; i < size2; i++) {
string top = q2.front();
q2.pop();
for (int j = 0; j < top.size(); j++) {
for (char change = 'a'; change < 'z'; change++) {
string next = top;
next[j] = change;
if (visited1.count(next)) return level2 + visited1[next];
if (wordSet.count(next)) {
visited2.insert({next, level2 + 1});
q2.push(next);
wordSet.erase(next);
}
}
}
}
level2++;
}
return 0;
}
};