【原创】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得自己都怕,唉。。
【原创】leetCodeOj --- Word Ladder II 解题报告 (迄今为止最痛苦的一道题)的更多相关文章
- LeetCode: Word Ladder II 解题报告
Word Ladder II Given two words (start and end), and a dictionary, find all shortest transformation s ...
- LeetCode: Word Break II 解题报告
Word Break II Given a string s and a dictionary of words dict, add spaces in s to construct a senten ...
- 【原创】leetCodeOj --- Jump Game II 解题报告
原题地址: https://oj.leetcode.com/problems/jump-game-ii/ 题目内容: Given an array of non-negative integers, ...
- 【LeetCode】212. Word Search II 解题报告(C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 前缀树 日期 题目地址:https://leetco ...
- 【LeetCode】140. Word Break II 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归求解 日期 题目地址:https://leetc ...
- 【LeetCode】244. Shortest Word Distance II 解题报告 (C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 字典保存出现位置 日期 题目地址:https://le ...
- [Leetcode Week5]Word Ladder II
Word Ladder II 题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/word-ladder-ii/description/ Descripti ...
- [leetcode]Word Ladder II @ Python
[leetcode]Word Ladder II @ Python 原题地址:http://oj.leetcode.com/problems/word-ladder-ii/ 参考文献:http://b ...
- 【leetcode】Word Ladder II
Word Ladder II Given two words (start and end), and a dictionary, find all shortest transformation ...
随机推荐
- datarow用linq查询
List<string> f_guids = (from DataRow dr in dt2.Rows select dr["f_GUID"].ToString()). ...
- Java泛型之<T>
这里不讲泛型的概念和基础知识,就单纯的就我的理解说一下泛型中的<T> 一. <T> 下面的一段码就可以简单使用了<T>参数,注释就是对<T>的解释. p ...
- 用C语言写解释器(一)——我们的目标
声明 为提高教学质量,我所在的学院正在筹划编写C语言教材.<用C语言写解释器>系列文章经整理后将收入书中"综合实验"一章.因此该系列的文章主要阅读对象定为刚学完C语言的 ...
- HDU 3571 N-dimensional Sphere(高斯消元 数论题)
这道题算是比较综合的了,要用到扩展欧几里得,乘法二分,高斯消元. 看了题解才做出来orz 基本思路是这样,建一个n*(n-1)的行列式,然后高斯消元. 关键就是在建行列式时会暴long long,所以 ...
- 算法起步之Prim算法
原文:算法起步之Prim算法 prim算法是另一种最小生成树算法.他的安全边选择策略跟kruskal略微不同,这点我们可以通过一张图先来了解一下. prim算法的安全边是从与当前生成树相连接的边中选择 ...
- Android开发之模板模式初探
模板模式我认为在Android的开发中是最长用到的,基本是随处可见的,认识该模式,有助于我们对Android的源代码及框架有一个更深层次的认识.那什么是模板模式呢,模板模式就是定义一个基本框架,将当中 ...
- Codeforces Round #296 (Div. 1) E. Triangles 3000
http://codeforces.com/contest/528/problem/E 先来吐槽一下,一直没机会进div 1, 马力不如当年, 这场题目都不是非常难,div 2 四道题都是水题! 题目 ...
- hdu3001(状压dp)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=3001 题意:n 个城市已经 m 条路 以及对应路费 c,要求遍历所有城市最少的路费,每个城市不能超过2 ...
- MVC数据验证使用小结
原文:MVC数据验证使用小结 描述:MVC数据验证使用小结 内容:display,Required,stringLength,Remote,compare,RegularExpression 本人最近 ...
- Android JNI 获取应用程序签名
使用Android JNI 获取应用程序签名. 获取基础上生成自己的签名password,这可以防止别人反编译找到自己的源代码password. jstring Java_com_masonsdk_j ...