Word Ladder
Problem
You are given two words, beginWord and endWord, and also a list of words wordList. All of the given words are of the same length, consisting of lowercase English letters, and are all distinct.
Your goal is to transform beginWord into endWord by following the rules:
- You may transform
beginWordto any word withinwordList, provided that at exactly one position the words have a different character, and the rest of the positions have the same characters. - You may repeat the previous step with the new word that you obtain, and you may do this as many times as needed.
Return the minimum number of words within the transformation sequence needed to obtain the endWord, or 0 if no such sequence exists.
Examples
Example 1:
Input: beginWord = "cat", endWord = "sag", wordList = ["bat","bag","sag","dag","dot"]
Output: 4
Explanation: The transformation sequence is "cat" -> "bat" -> "bag" -> "sag".
Example 2:
Input: beginWord = "cat", endWord = "sag", wordList = ["bat","bag","sat","dag","dot"]
Output: 0
Explanation: There is no possible transformation sequence from "cat" to "sag" since the word "sag" is not in the wordList.
Constraints
1 <= beginWord.length <= 101 <= wordList.length <= 100
You should aim for a solution with O((m ^ 2) * n) time and O((m ^ 2) * n) space, where n is the number of words and m is the length of the word.
Solution
BFS since each step is a word transition. Generate children if word distance is 1.
class Solution {
struct Node {
std::string state;
int g;
};
int word_distance(const std::string &s1, const std::string &s2) {
int count = 0;
for (int i = 0; i < std::min(s1.size(), s2.size()); ++i) {
count += (s1[i] != s2[i]) ? 1 : 0;
}
return count;
}
public:
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
std::queue<Node> open;
std::unordered_set<std::string> closed;
open.emplace(beginWord, 1);
closed.insert(beginWord);
while (!open.empty()) {
Node current = std::move(open.front());
open.pop();
// Solution check
if (current.state == endWord) {
return current.g;
}
// Generate children
for (const auto &word : wordList) {
if (closed.contains(word)) { continue; }
if (word_distance(word, current.state) == 1) {
open.emplace(word, current.g + 1);
closed.insert(word);
}
}
}
return 0;
}
};