140 Word Break II [Leetcode]
2015-10-06 11:43
441 查看
题目内容:
Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each word is a valid dictionary word.
Return all such possible sentences.
For example, given
s = “catsanddog”,
dict = [“cat”, “cats”, “and”, “sand”, “dog”].
A solution is [“cats and dog”, “cat sand dog”].
解题思路:
首先尝试简单的回溯,代码如下:
超时,特例如:
“aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab”
[“a”,”aa”,”aaa”,”aaaa”,”aaaaa”,”aaaaaa”,”aaaaaaa”,”aaaaaaaa”,”aaaaaaaaa”,”aaaaaaaaaa”]
还是需要把中间结果保存起来,使用动态规划来做。
使用二维数组
代码实现如下:
和前面的方法一样,遇到一样的情况时,会出现超时问题。原因猜想是字符串的拼接是一个比较耗时的操作,而上述代码求解中间结果需要大量的字符串拼接的操作。
如何把字符串拼接的中间结果操作忽略,直接计算出拼接的结果是下一步提速要解决的问题。值得注意的一点是,我们其实无需把字符串拼接的那么多中间结果都存起来。因为字符串是一样的,不一样的只是分割的位置,我们可以只把分割的位置记录下来。
另外,还有一个要考虑的是内存问题。如果把中间结果都叠加得保存起来,可能会需要大量的内存。因此我们修改了动态规划存储的中间结果的内容,即只存储由哪些下标可以跳转到当前的下标。这样,在最后通过一次回溯或者栈操作实现的DFS,就可以把最后的结果都保存下来。
代码如下,运行时间20ms,这里的回溯使用了递归实现,如果用栈应该能更快些。
Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each word is a valid dictionary word.
Return all such possible sentences.
For example, given
s = “catsanddog”,
dict = [“cat”, “cats”, “and”, “sand”, “dog”].
A solution is [“cats and dog”, “cat sand dog”].
解题思路:
首先尝试简单的回溯,代码如下:
class Solution { public: vector<string> wordBreak(string s, unordered_set<string>& wordDict) { vector<string> result; getSentences(wordDict, result, s, 0, ""); return result; } void getSentences(unordered_set<string>& wordDict, vector<string> &sentences, string &s, int index, string temp) { int size(s.size()); if(index == size) sentences.push_back(temp.substr(1)); for(int i = index; i < size; ++i) { string str = s.substr(index, i-index+1); if(wordDict.find(str) != wordDict.end()) { getSentences(wordDict, sentences, s, i+1, temp + " " + str); } } } };
超时,特例如:
“aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab”
[“a”,”aa”,”aaa”,”aaaa”,”aaaaa”,”aaaaaa”,”aaaaaaa”,”aaaaaaaa”,”aaaaaaaaa”,”aaaaaaaaaa”]
还是需要把中间结果保存起来,使用动态规划来做。
使用二维数组
vector<vector<string>>来存从i到j的在字典中的查找得到的中间结果,首先判断[0,i]的子串是否在字典中,若有,添加分割方法;其次,再从后向前判断[j,i]是否在字典中,若在字典中且[0,j]有解,那么添加方法。
代码实现如下:
class Solution { public: vector<string> wordBreak(string s, unordered_set<string>& wordDict) { int size(s.size()); vector<vector<string>> sentences; sentences.resize(size); for(int i = 0; i < size; ++i) { string sstr = s.substr(0, i+1); if(wordDict.find(sstr) != wordDict.end()) { sentences[i].push_back(sstr); } for(int j = i; j > 0; --j) { string tstr = s.substr(j, i-j+1); if(wordDict.find(tstr) != wordDict.end() && sentences[j-1].size() != 0) { for(int k = 0; k < sentences[j-1].size(); ++k) { string temp = sentences[j-1][k] + " " + tstr; sentences[i].push_back(temp); } } } } return sentences[size-1]; } };
和前面的方法一样,遇到一样的情况时,会出现超时问题。原因猜想是字符串的拼接是一个比较耗时的操作,而上述代码求解中间结果需要大量的字符串拼接的操作。
如何把字符串拼接的中间结果操作忽略,直接计算出拼接的结果是下一步提速要解决的问题。值得注意的一点是,我们其实无需把字符串拼接的那么多中间结果都存起来。因为字符串是一样的,不一样的只是分割的位置,我们可以只把分割的位置记录下来。
另外,还有一个要考虑的是内存问题。如果把中间结果都叠加得保存起来,可能会需要大量的内存。因此我们修改了动态规划存储的中间结果的内容,即只存储由哪些下标可以跳转到当前的下标。这样,在最后通过一次回溯或者栈操作实现的DFS,就可以把最后的结果都保存下来。
代码如下,运行时间20ms,这里的回溯使用了递归实现,如果用栈应该能更快些。
class Solution { public: vector<string> wordBreak(string s, unordered_set<string>& wordDict) { int size(s.size()); vector<vector<int>> sentences(size); for(int i = 0; i < size; ++i) { if(wordDict.find(s.substr(0, i+1)) != wordDict.end()) { sentences[i].push_back(0); } for(int j = i; j > 0; --j) { if(wordDict.find(s.substr(j, i-j+1)) != wordDict.end() && sentences[j-1].size() != 0) { sentences[i].push_back(j); } } } vector<string> result; getSentences(sentences, s, result, size-1, ""); return result; } void getSentences(vector<vector<int>> &breaks, string &s, vector<string> &output, int index, string mid_result) { if(index == -1) { if(mid_result != "") mid_result.pop_back(); output.push_back(mid_result); return; } int size(breaks[index].size()); for(int i = 0; i < size; ++i) { string temp = s.substr(breaks[index][i], index-breaks[index][i]+1) + " " + mid_result; getSentences(breaks, s, output, breaks[index][i]-1, temp); } } };
相关文章推荐
- phalapi-入门篇5(数据库操作和Model层)
- 一个队列类的实现(比delphi自带的速度快70倍)
- 360笔试题--找老乡
- UVA-863 Not so Mobile (简单二叉树)
- 恢复误删除的数据
- double check locking
- Docker学习笔记之ubuntu安装docker
- 不同场景下 MySQL 的迁移方案
- Adaboost 算法
- 随机生成名字或短句代码机
- 关于程序收到消息的顺序
- 初识Node.js
- 设置centos 系统时间与物理主机一致
- Linux网络编程入门 (转载)
- thinkphp-关于模板里 IP 地址的引用实例
- UVa 227 - Puzzle【字符串】
- cocos2d-x 瞬时动作
- [Python进阶-6]错误异常处理,断言assert,日志logging,单元测试,文档测试
- <<Vector Calculus>>笔记
- for循环大括号使用注意