【原创】leetCodeOj --- Word Ladder II 解题报告 (迄今为止最痛苦的一道题)
原题地址:
https://oj.leetcode.com/submissions/detail/19446353/
题目内容:
Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) 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"]
Return
[ ["hit","hot","dot","dog","cog"], ["hit","hot","lot","log","cog"] ]
Note:
- All words have the same length.
- All words contain only lowercase alphabetic characters.
方法:
在这里我分享下做这道题的心路,不,思路历程。
首先第一时间想到BFS,打算正常BFS,但是跟一般的BFS标记结点时不一样,由于可能通过不同路径到达,所以入队前不能标记结点,而是出队时扩展子结点前标记。
结果:TLE
然后考虑到,A、B、C、D到能某个结点,比如说F时,可能会重复计算F到终点的路径。考虑先BFS一次求出最短路径作为fullstep的参数,然后以类似动态规划的思路来记录下子问题的结果。其中具体的实现非常的复杂,同样的点,必须在固定的步数内才算有解。
结果:TLE
又想到,用unordered_set或者unordered_map装字符串,计算hash值时要遍历整个字符串,这个时候不如整数快。于是,就想到不记录字符串,而记录字符串的地址。字符串在从输入获得的set中。由于int损失了精度,就用long long来存。
结果:TLE
没办法了,想到返回子问题解的时候返回的是整个vector,有复制过程,那就换,换成指针,不复制整个vector了。
结果:TLE
干,那就提前建图!提前建好图,在图上做这一坨玩意,就不用老是重复拿26个字母穷举所有位置的情况了!
结果:TLE
最后的最后的最后,有点想放弃了,在意识模糊的情况下,就采用了提前建图 + BFS的思路。
结果居然TM AC了!
全部代码:
class Solution { public: unordered_map<long long,vector<long long>> map; // 提前建图 unordered_set<long long> mark; // 标记某个点是否已经访问过 struct node { int len; node *father; string *self; }; void generateMap(unordered_set<string> &dict) { unordered_set<string> :: iterator it1; unordered_set<string> :: iterator it2; unordered_set<long long> :: iterator it3; unordered_set<long long> used; for (it1 = dict.begin(); it1 != dict.end(); ++ it1) { vector<long long> tmp; map[(long long) & (*it1)] = tmp; } for (it1 = dict.begin(); it1 != dict.end(); ++ it1) { string *now = (string *) & (*it1); used.insert((long long) now); for (int i = 0; i < (*now).size(); ++ i) { char pre = (*now)[i]; for (int j = 'a'; j <= 'z'; ++ j) { if (j == pre) continue; (*now)[i] = j; it2 = dict.find(*now); if (it2 != dict.end()) { it3 = used.find((long long) & (*it2)); if (it3 == used.end()) { map[(long long) now].push_back((long long) & (*it2)); map[(long long) & (*it2)].push_back((long long) now); } } } (*now)[i] = pre; } } } vector<string> generateVector(node *tmp) { vector<string> res; while (tmp) { res.push_back(*(tmp->self)); tmp = tmp->father; } return res; } vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) { generateMap(dict); queue<node> myque; unordered_set<string> :: iterator it1; vector<vector<string>> res; vector<node> tmp; node startnode; it1 = dict.find(end); startnode.len = 1; startnode.father = NULL; startnode.self = (string *) & (*it1); myque.push(startnode); it1 = dict.find(start); string *fin = (string *)&(*it1); while (!myque.empty()) { node now = myque.front(); node *fa = new node; *fa = now; if (now.self == fin) { vector<string> lst = generateVector(fa); res.push_back(lst); int limit = now.len; myque.pop(); while (!myque.empty()) { node last = myque.front(); if (last.self == fin && last.len == limit) { lst = generateVector(&last); res.push_back(lst); } myque.pop(); } break; } mark.insert((long long)(now.self)); vector<long long> *vecptr = &map[(long long)(now.self)]; for (int i = 0; i < (*vecptr).size(); ++ i) { unordered_set<long long> :: iterator it2 = mark.find((*vecptr)[i]); if (it2 == mark.end()) { node child; child.len = now.len + 1; child.father = fa; child.self = (string *)(*vecptr)[i]; myque.push(child); } } myque.pop(); } return res; } };
后记:
之前那个BFS + 回溯 + DP的方法没能AC太可惜了,我那里指针玩的6得自己都怕,唉。。
posted on 2015-01-24 21:32 shadowmydx'sLab 阅读(199) 评论(0) 编辑 收藏 举报