Difficulty: Medium
Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence frombeginWord 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.
1.因为首单词和尾单词都没有加入wordList当中,所以先加入尾单词到wordList当中
2.从beginWord开始,进行广度优先搜索,每相邻的两个节点表示只有一个字母不同,进行BFS的关键问题在于如何做到不超时,这道题的做法就是不建图,因为建图的时间复杂度为O(n*n),如果n比较大的时候是会超时的,所以BFS的每条边都是把字符串的每个字母从‘a’到‘z’遍历,所以时间复杂度为O(sizeOfByte * 26)
3.在BFS的过程当中,一旦找到了endWord就立刻返回最短路径
但是按照这样的思路,我还是超时,因为这道题还有需要注意的点:
学会利用unordered_set,一开始我使用map来标记每个节点有没有访问过,然后也是超时,结果在网上看到别人通过的基本上都是利用了unordered_set,每次查找都是O(1)的时间复杂度,然后访问过的节点直接删掉就行了,所以我查了一下unordered_set
C++程序设计语言中,unordered_map、unordered_multimap、unordered_set、unordered_multiset是标准模板库(STL)提供的一类无序关联容器(unordered associative containers)。是通过哈希表实现的数据结构。无序是指元素的名字(或者键值)的存储是无序的;这与用平衡二叉树实现的元素名字是有序存储的“关联容器”是相对概念。所以通常比二叉树的存储方式可以提供更高的访问效率。
代码如下,时间复杂度为O(n * sizeOfByte * 26),n为单词的个数
class Solution {
public:
int BFS(unordered_set<string>& wordList, string& ta, string& tb)
{
queue<string> path;
queue<pair<string, int > > q;
q.push(make_pair(ta, 0));
while (!q.empty())
{
pair<string, int > entry = q.front();
q.pop();
for (int i = 0; i < (int)entry.first.size(); i++)
{
for (int j = 0; j < 26; j++)
{
char bit = 'a' + j;
if (entry.first[i] == bit) continue;
else {
string newstr = entry.first;
newstr[i] = bit;
unordered_set<string>::iterator exist = wordList.find(newstr);
if (exist != wordList.end() )
{
int newpath = entry.second+1;
q.push(make_pair(newstr, newpath));
if (newstr == tb) {
return newpath + 1;
}
wordList.erase(newstr);
}
}
}
}
}
return 0;
}
int ladderLength(string beginWord, string endWord, unordered_set<string>& wordList)
{
if (beginWord.size() == 0 || endWord.size() == 0 || beginWord.size() != endWord.size() || beginWord == endWord)
return 0;
wordList.insert(endWord);
//map<string, int> exist;
int res = BFS(wordList, beginWord, endWord);
return res;
}
};