# LC 127. Word Ladder
### [Problem link](https://leetcode.com/problems/word-ladder/)
###### tags: `leedcode` `hard` `c++` `python` `BFS`
A **transformation sequence** from word <code>beginWord</code> to word <code>endWord</code> using a dictionary <code>wordList</code> is a sequence of words <code>beginWord -> s<sub>1</sub> -> s<sub>2</sub> -> ... -> s<sub>k</sub></code> such that:
- Every adjacent pair of words differs by a single letter.
- Every <code>s<sub>i</sub></code> for <code>1 <= i <= k</code> is in <code>wordList</code>. Note that <code>beginWord</code> does not need to be in <code>wordList</code>.
- <code>s<sub>k</sub> == endWord</code>
Given two words, <code>beginWord</code> and <code>endWord</code>, and a dictionary <code>wordList</code>, return the **number of words** in the **shortest transformation sequence** from <code>beginWord</code> to <code>endWord</code>, or <code>0</code> if no such sequence exists.
**Example 1:**
```
Input: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]
Output: 5
Explanation: One shortest transformation sequence is "hit" -> "hot" -> "dot" -> "dog" -> cog", which is 5 words long.
```
**Example 2:**
```
Input: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]
Output: 0
Explanation: The endWord "cog" is not in wordList, therefore there is no valid transformation sequence.
```
**Constraints:**
- <code>1 <= beginWord.length <= 10</code>
- <code>endWord.length == beginWord.length</code>
- <code>1 <= wordList.length <= 5000</code>
- <code>wordList[i].length == beginWord.length</code>
- <code>beginWord</code>, <code>endWord</code>, and <code>wordList[i]</code> consist of lowercase English letters.
- <code>beginWord != endWord</code>
- All the words in <code>wordList</code> are **unique** .
## Solution 1 - BFS
#### Python
```python=
class Solution:
def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int:
if endWord not in wordList:
return 0
word_dict = defaultdict(list)
for word in wordList:
for i in range(len(word)):
word_dict[word[:i] + '*' + word[i + 1:]].append(word)
q = deque([(beginWord, 1)])
seen = set(beginWord)
while q:
curWord, path_len = q.popleft()
for i in range(len(curWord)):
midWord = curWord[:i] + '*' + curWord[i + 1:]
for word in word_dict[midWord]:
if word == endWord:
return path_len + 1
if word not in seen:
q.append((word, path_len + 1))
seen.add(word)
return 0
```
#### C++
```cpp=
class Solution {
public:
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
unordered_map<string, vector<string>> wordDict;
for (string& word: wordList) {
for (int i = 0; i < word.size(); i++) {
string tmp = word;
tmp[i] = '*';
wordDict[tmp].push_back(word);
}
}
queue<pair<string, int>> q;
q.push({make_pair(beginWord, 1)});
unordered_set<string> seen;
seen.insert(beginWord);
while (!q.empty()) {
pair<string, int> p = q.front();
q.pop();
for (int i = 0; i < p.first.size(); i++) {
string midWord = p.first.substr(0, i) + '*' + p.first.substr(i + 1);
for (string& word: wordDict[midWord]) {
if (word == endWord) {
return p.second + 1;
}
if (seen.find(word) == seen.end()) {
q.push(make_pair(word, p.second + 1));
seen.insert(word);
}
}
}
}
return 0;
}
};
```
>### Complexity
>| | Time Complexity | Space Complexity |
>| ----------- | --------------- | ---------------- |
>| Solution 1 | O($n^2$) | O($n^2$) |
## Note
x