Word Ladder
Given two words (start and end), and a dictionary, find the length of shortest transformation sequence from start to end, 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
分析:在该题上可以抽象出一个图,如果两个string有一个字母不同,那么这两个string相邻,那么接下来我们便可以用BFS得到最短路径。最初在判断相邻节点时,我求两个string的距离,如果为1,则判定该两个string相邻。
---恢复内容结束---
Given two words (start and end), and a dictionary, find the length of shortest transformation sequence from start to end, 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
分析:在该题上可以抽象出一个图,如果两个string有一个字母不同,那么这两个string相邻,那么接下来我们便可以用BFS得到最短路径。最初在判断相邻节点时,我求两个string的距离,如果为1,则判定该两个string相邻。但当dict很大时,这种方法会超时。相比之下,对于一个给定的string,产生所有跟它距离为1的string则省时的多。代码如下:
class Solution { public: int ladderLength(string start, string end, unordered_set<string> &dict) { int path_length = 1; unordered_map<string, bool> used; for(auto it = dict.begin(); it != dict.end(); it++) used[*it] = false; vector<string> pre, cur; pre.push_back(start); vector<string> end_set = next_string(end); while(!pre.empty()){ for(auto it = pre.begin(); it != pre.end(); it++){ vector<string> next_s = next_string(*it); for(auto ij = next_s.begin(); ij != next_s.end(); ij++){ if(dict.find(*ij) != dict.end() && !used[*ij]){ cur.push_back(*ij); used[*ij] = true; if(*ij == end) return path_length + 1; } } } pre = cur; cur.clear(); path_length++; } return 0; } vector<string> next_string(string s){ vector<string> res; for(int i = 0; i < s.length(); i++){ for(char c = 'a'; c <= 'z'; c++){ if(c != s[i]){ swap(c,s[i]); res.push_back(s); swap(c,s[i]); } } } return res; } };
一个更简洁的写法:
class Solution { public: int ladderLength(string start, string end, unordered_set<string> &dict) { if(start == end) return 1; int length = 1; unordered_set<string> prev; unordered_set<string> used; prev.insert(start); used.insert(start); while(!prev.empty()){ length++; unordered_set<string> cur; for(auto i = prev.begin(); i != prev.end(); i++){ string tmp = *i; for(int i = 0; i < tmp.length(); i++){ for(char c = 'a'; c <= 'z'; c++){ if(c != tmp[i]){ swap(c, tmp[i]); if(tmp == end) return length;//reach end if(dict.find(tmp) != dict.end() && used.find(tmp) == dict.end()){ cur.insert(tmp); used.insert(tmp); } swap(c, tmp[i]); } } } } prev = cur; } return 0; } };