139. Word Break
题目:
Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words.
For example, given
s = "leetcode"
,
dict = ["leet", "code"]
.
Return true because "leetcode"
can be segmented as "leet code"
.
链接: http://leetcode.com/problems/word-break/
题解:
求字符串是否能被分为字典中的单词。这道题一上来就想到用DFS, 就是假如s.substring(0,i)可以在字典中被找到,那么接下来只需要看s.substring(i,len) 是否能在字典中被找到, 当s.length() = 0时便利完毕,返回true。需要注意的是DFS要remove掉字典中的单词,比如这个case : s = "aaaaaaa", wordDict = {"aaa", "aaaa"},假如不remove掉"aaa",则结果不正确。 时间复杂度这个很有意思,因为自Java 7 update 6开始,string.substring()这个method的时间复杂度从O(1)变成了O(n), 以前是同一个char[],现在会重新建立一个char[]。 所以下面解法的Time Complexity应该是O(n3)。也需要注意边界,因为substring方法得到的结果是前闭后开。 还看到discuss以及小莹子和code ganker使用dp来解决这道题,二刷时要好好参考一下。 (Time Complexity 这块我可能是错的,不少人说是O(2n), 还要再好好分析)。WordBreak I和Word Break II一定要好好想清楚。
Time Complexity - O(n3), Space Complexity - O(n2).
public class Solution {
public boolean wordBreak(String s, Set<String> wordDict) {
if(s == null || wordDict == null)
return false;
if(s.length() == 0)
return true;
int len = s.length(); for(int i = 1; i <= len; i++) {
String frontPart = s.substring(0, i);
String backPart = s.substring(i, len);
if(wordDict.contains(frontPart)) {
if(wordBreak(backPart, wordDict))
return true;
wordDict.remove(frontPart);
}
} return false;
}
}
二刷:
使用了dfs。这里我们比较容易就想到可以把这个大问题转换为子问题递归求解。
- 先来看边界条件,当s == null或者 wordDict == null的时候,我们要返回false
- 在字符串s长度为0的时候,这时候是计算完毕了所有的match,我们返回true。 (3/15/2016时 这道题好像少test case, 当s = ""并且dict = {"leet", "code"}的时候,系统抛出ArrayIndexOutofBoundsException异常
- 当dict中含有front的时候,我们递归求解,看是否wordBreak(back, wordDict)为true, 假如这个结果为true,我们直接返回true
- 否则,说明我们这种split方法不对,我们这时候要做一个很给力的剪枝,wordDict.remove(front), 把front这个单词从wordDict里面去除掉,免得后面继续做多余运算。
- 遍历完字符串后依然没有返回true的话,我们返回false
- 假如不算substring带来的cost的话,时间复杂度应该是O(n ^ 2), 空间复杂度是在一个call stack里的小字符串长度综合,应该是O(n)。
- 还有很多题友使用动态规划求解。 我自己的动态规划很烂,非常羡慕。
接下来我们从0开始遍历字符串, 我们把字符串分为两个部分,front 和 back, front = s.substring(0, i + 1), back = s.substring(i + 1)
Java:
Time Complexity - O(n ^ 2), Space Complexity - O(n)
public class Solution {
public boolean wordBreak(String s, Set<String> wordDict) {
if (s == null || wordDict == null) {
return false;
}
if (s.equals("")) {
return true;
}
for (int i = 0; i < s.length(); i++) {
String substr = s.substring(0, i + 1);
if (wordDict.contains(substr)) {
if (wordBreak(s.substring(i + 1), wordDict)) {
return true;
}
wordDict.remove(substr);
}
}
return false;
}
}
dp:
建立一个boolean[]数组dp来保存结果,dp[i]表示到i这位我们是否满足分割成功。 初始化dp[0] = true。 使用一个双重循环来遍历字符串,每次假如满足条件dp[j] && s.substring(j, i), 我们可以设置dp[i] = true,说明到i这一位的分割是成功的。 最后我们返回dp[len].
Time Complexity - O(n ^ 2), Space Complexity - O(n)
public class Solution {
public boolean wordBreak(String s, Set<String> wordDict) {
if (s == null || wordDict == null) {
return false;
}
int len = s.length();
boolean[] dp = new boolean[len + 1];
dp[0] = true; for (int i = 1; i <= len; i++) {
for (int j = 0; j < i; j++) {
if (dp[j] && wordDict.contains(s.substring(j, i))) {
dp[i] = true;
}
}
}
return dp[len];
}
}
三刷:
这道题目其实没有说清楚的是,wordDict中的元素是否可以被重复使用。测试了几次以后发现是可以的。比如S = "aa",wordDict = ["a"],结果为true。面试的时候一定要注意问清楚面试官的意思,一点一点clarify问题。
Java:
Recursive:
Time Complexity - O(n ^ 2), Space Complexity - O(n ^ 2)
为什么Time Complexity是 O(n ^ 2)呢? (worst case)
对于worst case来说,递归项T(n) = T(n - 1) + 1,所以这是一个线性,再加上外层O(n)的遍历,综合起来,不考虑substring的话,就是O(n ^ 2)。空间复杂度也是 O(n ^ 2), 就是递归栈的深度 n * 外层遍历 n。
public class Solution {
public boolean wordBreak(String s, Set<String> wordDict) {
if (s == null || wordDict == null) return false;
if (s.equals("")) return true;
for (int i = 1; i <= s.length(); i++) {
String front = s.substring(0, i);
if (wordDict.contains(front)) {
if (wordBreak(s.substring(i), wordDict)) return true;
wordDict.remove(front);
}
}
return false;
}
}
一维dp:
主要就是做一个boolean[len + 1]数组,然后根据之前保存的信息dp[j]与从j到i的新单词s.substring(j, i)来看能否从dp[j]扩展到dp[i]
Time Complexity - O(n ^ 2), Space Complexity - O(n)
public class Solution {
public boolean wordBreak(String s, Set<String> wordDict) {
if (s == null || wordDict == null) return false;
int len = s.length();
boolean[] dp = new boolean[len + 1];
dp[0] = true;
for (int i = 1; i <= len; i++) {
for (int j = 0; j < i; j++) {
if (dp[i]) break;
if (dp[j] && wordDict.contains(s.substring(j, i))) dp[i] = true;
}
}
return dp[len];
}
}
Reference:
http://www.cnblogs.com/springfor/p/3874731.html
http://blog.csdn.net/linhuanmars/article/details/22358863
https://leetcode.com/discuss/1523/who-can-show-me-a-dp-solution-thanks
https://leetcode.com/discuss/8479/a-solution-using-bfs
https://leetcode.com/discuss/8482/a-java-solution-with-similar-dp-idea
https://leetcode.com/discuss/11462/anyone-who-knows-time-complexity-recursion-with-dfs-here-code
https://leetcode.com/discuss/18904/java-implementation-using-dp-in-two-ways
https://leetcode.com/discuss/26956/dfs-with-path-memorizing-java-solution
https://leetcode.com/discuss/21709/dynamic-programming-simple-fast-solution-with-optimization
https://leetcode.com/discuss/41411/4-lines-in-python
https://leetcode.com/discuss/39224/a-short-dp-c%23-solution
https://leetcode.com/discuss/63212/java-solution-using-dp
139. Word Break的更多相关文章
- leetcode 139. Word Break 、140. Word Break II
139. Word Break 字符串能否通过划分成词典中的一个或多个单词. 使用动态规划,dp[i]表示当前以第i个位置(在字符串中实际上是i-1)结尾的字符串能否划分成词典中的单词. j表示的是以 ...
- 139. Word Break 以及 140.Word Break II
139. Word Break Given a non-empty string s and a dictionary wordDict containing a list of non-empty ...
- Leetcode#139 Word Break
原题地址 与Word Break II(参见这篇文章)相比,只需要判断是否可行,不需要构造解,简单一些. 依然是动态规划. 代码: bool wordBreak(string s, unordered ...
- [LeetCode] 139. Word Break 单词拆分
Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine ...
- 【LeetCode】139. Word Break 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...
- 139. Word Break(动态规划)
Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine ...
- LeetCode 139. Word Break单词拆分 (C++)
题目: Given a non-empty string s and a dictionary wordDict containing a list of non-emptywords, determ ...
- [LC] 139. Word Break
Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine ...
- leetcode 139. Word Break ----- java
Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separa ...
随机推荐
- ACM——搜索(一)
南邮OJ——1108 搜索(一) 时间限制(普通/Java):3500MS/10500MS 运行内存限制:65536KByte总提交:1023 测试通过:367 ...
- CefSharp开源库的使用(一)
关于CEF: 嵌入式Chromium框架(简称CEF) 是一个由Marshall Greenblatt在2008建立的开源项目,它主要目的是开发一个基于Google Chromium的Webbrows ...
- 对象创建型模式------Singleton(单例模式)
地址:http://blog.csdn.net/wuzhekai1985/article/details/6665869.仅供自己参考学习. 单例模式:保证一个类仅有一个实例,并提供一个访问它的全局节 ...
- JavaScript高级程序设计(七):JavaScript中的in关键字
in 使用点一: 在js中,for--in用于遍历一个对象的属性,把对象的属性名和属性值都提出来. var obj = { "key1":"value1", & ...
- 用JQuery编写textarea,input,checkbox,select
今天学习怎样用JQuery编写一些小的代码,小小的试了一下编写一个textarea,代码如下: <!DOCTYPE HTML> <html lang="en"&g ...
- Mysql 创建联合索引注意事项
当一个表有多条索引可走时, Mysql 根据查询语句的成本来选择走哪条索引, 联合索引的话, 它往往计算的是第一个字段(最左边那个), 这样往往会走错索引. 如: 索引Index_1(Crea ...
- iOS对textField进行字符长度限制的办法
在项目开发过程中,遇到这么一个需求,编辑标签时,输入的最大长度需要限制为24个字节. 查阅了一些材料,并参考了之前项目的相关处理办法,今天在这里总结一下解决方案. 1.写一个截取字符串的方法,将超长的 ...
- UIMenuController/UIPasteboard(1) 制作一个可以粘贴复制的Label
效果如下: 苹果只放出来了 UITextView,UITextField,webView三个控件的剪贴板,所以我们要自定义可以复制粘贴的控件,首先需要打开UIResponder的两个方法: - ( ...
- iOS开发,多个button数组,每个数组只能选中5项,多个数组只能选择3个。
由于常用xib,所以不想用代码写那么多个button.而且也懒的算位置 直接xib拉线成四个数组.水果,零食,饮料,甜点. 入题实现的功能就是,在这四个数组之中只能在3个数组只选中5项.有点绕(就比如 ...
- ios数据库FMDB
一.下载fmdb类库 二.添加libsqulite3.0.dylib 三.添加头文件#import "FMDB.h" 四.打开数据库 a.设置路径NSString *path = ...