LeetCode Word Ladder
Given two words (beginWord and endWord), and a dictionary, find the length of shortest transformation sequence from beginWord to endWord, such that:
- Only one letter can be changed at a time
- Each intermediate word must exist in the dictionary
For example,
Given:
start = "hit"
end = "cog"
dict = ["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.5年前提交的,失去很多,得到的却寥寥无几。还是看了一些解答自己先写个BFS的:
class Solution { public: int ladderLength(string beginWord, string endWord, unordered_set<string>& wordDict) { queue<string> que; que.push(beginWord); wordDict.insert(endWord); int level = 0; while (!que.empty()) { level++; int size = que.size(); for (int i=0; i<size; i++) { string str = que.front(); que.pop(); if (str == endWord) { return level; } int len = str.size(); for (int k=0; k<len; k++) { for (char ch='a'; ch <= 'z'; ch++) { if (str[k] == ch) { continue; } char t = str[k]; str[k] = ch; if (wordDict.count(str) > 0) { wordDict.erase(str); que.push(str); } str[k] = t; } } } } return 0; } };
没什么优化的地方,240+ms
另外从discuss里找了个递归的解法,60ms
class Solution { public: int ladderLength(string beginWord, string endWord, unordered_set<string>& wordDict) { unordered_set<string> s1 = {beginWord}; // Front end unordered_set<string> s2 = {endWord}; // Back end wordDict.erase(beginWord); wordDict.erase(endWord); return ladderLength(s1, s2, wordDict, 1); } private: int ladderLength(unordered_set<string>& s1, unordered_set<string>& s2, unordered_set<string>& wordDict, int level) { if (s1.empty()) // We can't find one. return 0; unordered_set<string> s3; // s3 stores all words 1 step from s1. for (auto word : s1) { for (auto& ch : word) { auto originalCh = ch; for (ch = 'a'; ch <= 'z'; ++ ch) { if (ch != originalCh) { if (s2.count(word)) // We found one. return level + 1; if (wordDict.count(word)) { wordDict.erase(word); // Avoid duplicates. s3.insert(word); } } } ch = originalCh; } } // Continue with the one with smaller size. return (s2.size() <= s3.size()) ? ladderLength(s2, s3, wordDict, level + 1) : ladderLength(s3, s2, wordDict, level + 1); } };
如果最后一个return中的判断不加的花,时间在340+ms。这个解法不是单向的从start往end走,他们的关系是对等的,可以根据需要进行双向的靠近。它会根据两者集合数量选择较少的那个来生成相差一次字母转换的一个集合来替换自己,进行下一步运算。如果发现本集合中有可以通过一次转换到另外一个集合中,则当前所进行过的转换次数即为最少转换次数。