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.
因为之前一直没自己写过Dijkstra算法,而且最开始感觉这题就是先转成图再用Dijkstra求最短路径,所以就一直没做,昨天复习了一下Dijkstra算法,打算把这题A掉,没想到居然爆内存了。
网上搜了下别人的代码,发现不用先转化成图,求边的时候直接枚举‘a’到‘z’就可以了,然后BFS。
1 class Solution { 2 public: 3 int ladderLength(string start, string end, unordered_set<string> &dict) { 4 if (start.length() != end.length()) return 0; 5 if (start.empty() || end.empty()) return 0; 6 queue<string> path; 7 path.push(start); 8 dict.erase(start); 9 int len = 1, cnt = 1; 10 while (!dict.empty() && !path.empty()) { 11 string cur = path.front(); 12 path.pop(); 13 --cnt; 14 for (int i = 0; i < cur.size(); ++i) { 15 string tmp = cur; 16 for (char j = 'a'; j <= 'z'; ++j) { 17 if (tmp[i] == j) continue; 18 tmp[i] = j; 19 if (tmp == end) return len + 1; 20 if (dict.find(tmp) != dict.end()) { 21 path.push(tmp); 22 dict.erase(tmp); 23 } 24 } 25 } 26 if (cnt == 0) { 27 ++len; 28 cnt = path.size(); 29 } 30 } 31 return 0; 32 } 33 };
下面是Dijsktra算法,不过超内存了。
1 class Solution { 2 public: 3 bool match(const string &s1, const string &s2) { 4 if (s1.length() != s2.length()) return false; 5 int cnt = 0; 6 for (int i = 0; i < s1.length(); ++i) { 7 if (s1[i] != s2[i]) ++cnt; 8 if (cnt > 1) return false; 9 } 10 return cnt == 1 ? true : false; 11 } 12 13 void buildGraph(vector<vector<int> > &graph, unordered_set<string> &dict, string start, string end, int &start_idx, int &end_idx) { 14 dict.insert(start); 15 dict.insert(end); 16 vector<string> str_idx(dict.size()); 17 int idx = 0; 18 for (auto i : dict) { 19 str_idx[idx] = i; 20 if (i == start) start_idx = idx; 21 if (i == end) end_idx = idx; 22 ++idx; 23 } 24 graph.assign(str_idx.size(), vector<int>(str_idx.size(), INT_MAX)); 25 for (int i = 0; i < str_idx.size(); ++i) { 26 for (int j = 0; j < str_idx.size(); ++j) { 27 if (match(str_idx[i], str_idx[j])) { 28 graph[i][j] = graph[j][i] = 1; 29 } 30 } 31 } 32 } 33 34 int dijkstra(vector<vector<int> > &graph, int start_idx, int end_idx) { 35 int N = graph.size(); 36 vector<bool> s(N, false); 37 vector<int> dist(N, 0); 38 int u = start_idx; 39 for (int i = 0; i < N; ++i) { 40 dist[i] = graph[start_idx][i]; 41 } 42 dist[start_idx] = 0; 43 s[start_idx] = true; 44 for (int i = 0; i < N; ++i) { 45 int tmp_max = INT_MAX; 46 for (int j = 0; j < N; ++j) { 47 if (!s[j] && tmp_max > dist[j]) { 48 u = j; 49 tmp_max = dist[j]; 50 } 51 } 52 s[u] = true; 53 if (u == end_idx) return dist[u] + 1; 54 for (int j = 0; j < N; ++j) { 55 if (!s[j] && graph[u][j] < INT_MAX) { 56 dist[j] = min(dist[j], dist[u] + graph[u][j]); 57 } 58 } 59 } 60 } 61 62 int ladderLength(string start, string end, unordered_set<string> &dict) { 63 vector<vector<int> > graph; 64 int start_idx, end_idx; 65 buildGraph(graph, dict, start, end, start_idx, end_idx); 66 return dijkstra(graph, start_idx, end_idx); 67 } 68 };