LeetCode - Word Break II
来源:互联网 发布:天猫品类销售数据 编辑:程序博客网 时间:2024/09/21 09:21
题注
刚才一直在和我的导师进行交流,又学到了很多东西。说实话,现在几位教导过我的老师真是我人生的指明灯,我非常幸运能在高校中遇到这些真正为学生考虑的老师,而且还不止一位!这样也让我更有动力进行学习和研究呀!
回到主题,继续做LeetCode,有了Word Break的基础,正好也挑战一下Word Break II。Word Break II的思路和Word Break很像,但是有一个很重要的问题需要注意。
题目
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"]
分析
这次不仅仅是返回是否存在Word Break了,连结果也需要一并返回。这很容易看出是一个算法复杂度非常高的问题,举个例子:
s = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
dict = ["a", "aa", "aaa", "aaaa"]
大家可以很直观的想想,这结果得有多少个… 因此,在糟糕情况下,这是一个时间和空间复杂度都非常高的问题。
我的想法是延续Word Break的思路。但是,我们要对于每一位都存储可能的组合结果,举个例子:
s = "aaaaaa";
dict = ["a", "aa", "aaa"]
对于s.substring(0,1),有一种结果"a";
对于s.substring(0,2),有两种结果,一种是直接的"aa",一种是从s.substring(0,1)再接上后面的"a",即为“a a”;
对于s.substring(0,3),可以是s.substring(0,1)拼上s.substring(1,3),可以是s.substring(0,2)拼上s.substring(2,3),也可以是s.substring(0,3);
这样思路就清楚了,仍然用动态规划的方法,对于s.substring(0, i),要不为s.substring(0, j) + " " +s.substring(j, i),其中j < i,要不为s.substring(0,i);和前面Word Break结合起来,就得到了最后的结果了。
然而,如果仅仅如此修改,是通过不了的,我首先提交了这样的代码:
public class Solution { public ArrayList<String> wordBreak(String s, Set<String> dict) { int length = s.length(); boolean[] can = new boolean[length+1]; ArrayList<String>[] canList = new ArrayList[length+1]; for (int i=1; i <= length; i++){ canList[i] = new ArrayList<String>(); } can[0] = true; for (int i = 1; i <= length; i++) { for (int j = 0; j < i; j++) { if (can[j] && dict.contains(s.substring(j, i))) { can[i] = true; if (j == 0){ canList[i].add(s.substring(j, i)); }else{ for (int k=0; k<canList[j].size(); k++){ canList[i].add(canList[j].get(k) + " " + s.substring(j, i)); } } } } } return canList[length]; }}结果出现了Time Limit Exceeded,其例子为:
s = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab";
dict = ["a","aa","aaa","aaaa","aaaaa","aaaaaa","aaaaaaa","aaaaaaaa","aaaaaaaaa","aaaaaaaaaa"];
然而从我们的分析中,可以知道这样的s和dict一定会出现Time Limit Exceeded的嘛!我试着在Eclipse中运行了一下,代码如下:
public class Solution { public ArrayList<String> wordBreak(String s, Set<String> dict) { int length = s.length(); boolean[] can = new boolean[length+1]; ArrayList<String>[] canList = new ArrayList[length+1]; for (int i=1; i <= length; i++){ canList[i] = new ArrayList<String>(); } can[0] = true; for (int i = 1; i <= length; i++) { for (int j = 0; j < i; j++) { if (can[j] && dict.contains(s.substring(j, i))) { can[i] = true; if (j == 0){ canList[i].add(s.substring(j, i)); }else{ for (int k=0; k<canList[j].size(); k++){ canList[i].add(canList[j].get(k) + " " + s.substring(j, i)); } } } } } return canList[length]; } public static void main(String[] args){ String s = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab"; Set<String> dict = new HashSet<String>(); dict.add("a"); dict.add("aa"); dict.add("aaa"); dict.add("aaaa"); dict.add("aaaaa"); dict.add("aaaaaa"); dict.add("aaaaaaa"); dict.add("aaaaaaaa"); dict.add("aaaaaaaaa"); dict.add("aaaaaaaaaa"); ArrayList<String> result = new Solution().wordBreak(s, dict); for (int i=0; i<result.size(); i++){ System.out.println(result.get(i)); } }}运行一段时间后,结果出现了一个Exception:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOfRange(Unknown Source)
at java.lang.String.<init>(Unknown Source)
at java.lang.StringBuilder.toString(Unknown Source)
at Solution.wordBreak(Solution.java:23)
at Solution.main(Solution.java:45)
实际上,因为我们对每一个s.substring(0, i)都进行了结果的计算,而这个例子给的又特殊,因此程序直接出现OutOfBound了。可是,仔细一想,都OutOfBound了,那结果还怎么存储并返回的呢?观察一下才知道,原来给的这个例子中,s的末尾是个"b",也就是说这根本没有Word Break!所以我们可以先用Word Break中的代码,在短时间内判断有没有正确的结果,如果有再计算结果。将Word Break的代码增加到Word Break II中,就得到正确的结果了。
代码
public class Solution { public ArrayList<String> wordBreak(String s, Set<String> dict) { int length = s.length(); if (!this.isWordBreak(s, dict)){ return new ArrayList<String>(); } boolean[] can = new boolean[length+1]; ArrayList<String>[] canList = new ArrayList[length+1]; for (int i=1; i <= length; i++){ canList[i] = new ArrayList<String>(); } can[0] = true; for (int i = 1; i <= length; i++) { for (int j = 0; j < i; j++) { if (can[j] && dict.contains(s.substring(j, i))) { can[i] = true; if (j == 0){ canList[i].add(s.substring(j, i)); }else{ for (int k=0; k<canList[j].size(); k++){ canList[i].add(canList[j].get(k) + " " + s.substring(j, i)); } } } } } return canList[length]; } public boolean isWordBreak(String s, Set<String> dict) { int length = s.length(); boolean[] can = new boolean[length+1]; can[0] = true; for (int i = 1; i <= length; i++) { for (int j = 0; j < i; j++) { if (can[j] && dict.contains(s.substring(j, i))) { can[i] = true; break; } } } return can[length]; }}
- [leetcode]Word Break II
- LeetCode:Word Break II
- Leetcode: Word Break II
- [LeetCode] Word Break II
- [LeetCode]Word Break II
- LeetCode | Word Break II
- [LeetCode] - Word Break II
- LeetCode - Word Break II
- Leetcode Word Break II
- [LeetCode] Word Break II
- Word Break II -- LeetCode
- LeetCode (Word Break II )
- Leetcode--Word Break II
- Leetcode: Word Break II
- LeetCode Word Break II
- Word Break II leetcode
- [leetcode]Word Break II
- leetcode -- word break II
- REST(Representational State Transfer表述性状态转移)
- Protocol Buffers 编译安装使用Protoc2.5 on Centos6.4
- 共享库
- 使用hibernate模拟触发器&拦截器方式
- 五十二 对于按位存储的编译器优化
- LeetCode - Word Break II
- 缓冲区溢出
- 元宵遇上情人节 8款热门平板送心仪的TA
- 读者调查—合作模式:开元工作模式
- MFC入门学习之控件(5)标签控件List Control的添加和使用(中)
- 解决问题:有几个bing?
- Google Java编程风格指南中文版
- linux 延时及时间函数总结
- Dojo 事件<10>