有道的一道面试题 突然觉得跟word ladder有些关系
2014-05-26 13:45
176 查看
首先,在有道面实习的时候,问到了这样的一个题目,就是说一个图像识别类似的问题,假设改图片中就是一个英语单词。该单词的长度是未知的,该单词的每一位都太模糊了,但是大概可以给几个候选。比如:原本的字母可能是a, 但是由于图像太模糊了,只能猜大概是 d,o,b 3个字母其中一个。那么最后要求输出所有的单词种类。
DFS的话。由于单词本身的长度太长的话,递归的深度可能太深了。当时我确实没想到什么好点子,今天突然做到word ladder 这道题,似乎是可以使用父节点之类的什么东西。没有想明白,如果大家有什么好的idea,可以告诉我,不胜感激。
PS:当时面试官提醒的是 DFS 加一个小trick之类的。至今还没想明白。
题目描述:
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 =
end =
dict =
As one shortest transformation is
return its length
要求最短的路径,BFS当然是首选。直接可以得到最短路径。因此代码如下:
对于上述代码,值得一提的是,每次在访问了当前单词之后,必须恢复原来的单词。
word ladder 2, 跟上面的题目一致,不再是输出长度,而是得到所有可能的路径,这里有个小窍门:
如果要输出所有的路径,如果对已经走过的路径进行保存的话,空间是会非常大的,因为每一个节点再最坏情况下有26个后继节点,由于这其实是一个树状的结构。我们可以通过保存每一个节点的父亲节点(唯一的),即可节省空间。
因此,代码如下:
DFS的话。由于单词本身的长度太长的话,递归的深度可能太深了。当时我确实没想到什么好点子,今天突然做到word ladder 这道题,似乎是可以使用父节点之类的什么东西。没有想明白,如果大家有什么好的idea,可以告诉我,不胜感激。
PS:当时面试官提醒的是 DFS 加一个小trick之类的。至今还没想明白。
题目描述:
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.
要求最短的路径,BFS当然是首选。直接可以得到最短路径。因此代码如下:
const char alphabet[] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'}; class Solution { public: int ladderLength(string start, string end, unordered_set &dict) { if(dict.size() == 0 || start == end) { return 0; } int curStep = 1; int minStep = INT_MAX; unordered_set visited; queue prev; queue next; prev.push(start); int n = start.size(); string curWord; string temp; while(!prev.empty()) { curStep += 1; while(!prev.empty()) { temp = prev.front(); //cout << curStep << " " << temp << endl; prev.pop(); for(int i = 0 ; i < n; ++i) { curWord = temp; for(int j = 0 ; j < 26; ++j ) { if(curWord[i] == alphabet[j]) { continue; } curWord[i] = alphabet[j]; //cout << curWord << endl; if(curWord == end) { return curStep; } if(dict.find(curWord) != dict.end() && visited.find(curWord) == visited.end()) { //cout << "xq" << endl; visited.insert(curWord); next.push(curWord); } curWord = temp; //!!!!! } } } swap(prev, next); } return 0; } };
对于上述代码,值得一提的是,每次在访问了当前单词之后,必须恢复原来的单词。
word ladder 2, 跟上面的题目一致,不再是输出长度,而是得到所有可能的路径,这里有个小窍门:
如果要输出所有的路径,如果对已经走过的路径进行保存的话,空间是会非常大的,因为每一个节点再最坏情况下有26个后继节点,由于这其实是一个树状的结构。我们可以通过保存每一个节点的父亲节点(唯一的),即可节省空间。
因此,代码如下:
class Solution { private: void buildPath( unordered_map > & parent, const string start, vector > &ret, vector &curPath, const string word) { // cout << "build path..." << endl; curPath.push_back(word); if(word == start) { ret.push_back(curPath); reverse(ret.back().begin(), ret.back().end()); } else { for(int i = 0 ; i < parent[word].size() ; ++i) { buildPath( parent, start,ret, curPath, parent[word][i]); } } curPath.pop_back(); } public: vector< vector< string> > findLadders( string start, string end, unordered_set & dict) { vector > ret; //必须不包含重复的元素??? unordered_set cur, next; cur.insert(start); unordered_set visited; unordered_map > parent; bool found = false; string curWord, tempWord; while(!cur.empty() && !found) { //cout << "xq" << endl; found = false; //将该层的所有节点入栈 for(auto it = cur.begin(); it != cur.end() ; ++it) visited.insert(*it); for(auto it = cur.begin() ; it != cur.end() ; ++it) { curWord = *it; for(int i = 0 ; i < curWord.size() ; ++i) { tempWord = curWord; for(char c = 'a' ; c <= 'z' ; ++c) { if(tempWord[i] == c) continue; tempWord[i] = c; if(tempWord == end) { found = true; //在这一层找到了该节点,下面的层就不用管了,但是当前层的单词得考虑完毕。所以不用break } if ( visited.count(tempWord) == 0 && ( dict.count(tempWord) > 0 || tempWord == end )) { parent[tempWord].push_back(curWord); next.insert(tempWord); } tempWord = curWord; } } } cur.clear(); swap(cur, next); } if(found) { vector curPath; //为了下面的函数的递归调用 buildPath(parent, start, ret, curPath, end); } return ret; } };。
相关文章推荐
- 一道mysql面试题,觉得有些伤脑经,记录下来
- 突然有一道题,让我觉得是反转字符串的正确用法...
- 今天做到一道面试题:Handler+Looper+MessageQueue+Message的关系
- 一道面试题:解析方法中对象存放以及堆栈之间的关系
- 由一个博问学到的SQL查询方法 (一道多对多关系查询的面试题)
- Java Word Ladder(字梯)
- 2015百度一道面试题引发的思考(shell脚本和网络)
- 关于global和$GLOBALS[]的一道经典面试题
- 一道经典的面试题:如何从N个数中选出最大(小)的n个数?
- 一道传说中的阿里面试题
- 一道月薪数万的面试题(附讨论分析结果)
- 突然觉得这个世界好像不正常运作了
- word在使用中突然变为“只读”
- 一道算法题:华为面试题
- 一道sql 的面试题
- JavaScript函数内部修改全局变量的问题【一道面试题】
- 一道并发和锁的golang面试题
- 回顾JavaSE(5)-String(4)7行代码分析一道关于String拼接的经典面试题
- 由一道面试题引发的思考
- Leetcode 126. Word Ladder II