139. Word Break
2016-12-01 23:13
295 查看
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 =
dict =
Return true because
这是以前刷题写的博客,尼玛刷完就忘了,当时一心想着刷题的数量,到现在就TMD感觉什么都没刷一样,看来刷题应有的姿势是:刷题自是手段,刷的过程中学习别人怎么思考的才是王道,不扯了,总结
第一反应就是递归,很快写出
import java.util.List;
public class Solution {
public boolean wordBreak(String s, List<String> wordDict) {
if("".equals(s)) return true;
for(String t : wordDict) {
if(s.startsWith(t) && wordBreak(s.substring(t.length()), wordDict))
return true;
}
return false;
}
}
TLE没商量,那就用Hash memorize吧
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class recrusion {
Set<String> canBreak = new HashSet<String>();
public boolean wordBreak(String s, List<String> wordDict) {
4000
if("".equals(s) || canBreak.contains(s)) return true;
for(String t : wordDict) {
if(s.startsWith(t) && wordBreak(s.substring(t.length()), wordDict)) {
canBreak.add(s);
return true;
}
}
return false;
}
}
还是TLE,考虑到已经有递归和优化的形式了,为什么不用DP呢?但是这个TMD的递归好像不能划分子问题,即使知道了dp[i]之前的值,好像跟求解dp[i]并没有什么关系,自此就卡主了。‘
那就在Discuss里面看答案吧,我差,有DFS,BFS,DP,为毛老子不行
然后发现:在DFS的时候每一步决策他们看的是String s的index,而不是在dict里面选择一个就继续进行下一步,好,那我改
public class recrusion2 {
Set<String> canBreak = new HashSet<String>();
public boolean wordBreak(String s, List<String> wordDict) {
return dfs(s, 0, wordDict);
}
private boolean dfs(String s, int start, List<String> wordDict) {
if(start == s.length() || canBreak.contains(s.substring(start))) return true;
for(int i=start; i<s.length(); i++) {
if(wordDict.contains(s.substring(start, i+1)) && dfs(s, i+1, wordDict)) {
canBreak.add(s);
return true;
}
}
return false;
}
}
继续TLE,仔细看,发现canBreak这个set根本就没有起到作用,因为他是在return true的时候才会有String被加到里面,这是已经可以确定答案就是true,TMD的还要加个蛋啊
那就弄个cannotBreak的set吧
public class recursion4 {
Set<String> cannotBreak = new HashSet<String>();
public boolean wordBreak(String s, List<String> wordDict) {
return dfs(s, 0, wordDict);
}
private boolean dfs(String s, int start, List<String> wordDict) {
if(start == s.length()) return true;
if(cannotBreak.contains(s.substring(start))) return false;
for(int i=start; i<s.length(); i++) {
if(wordDict.contains(s.substring(start, i+1))) {
if(dfs(s, i+1, wordDict))
return true;
else
cannotBreak.add(s.substring(i+1));
}
}
return false;
}
}
终于AC,划分子结构也挺明了的了,按照递归的反方向DP就OK
import java.util.List;
public class Solution {
public boolean wordBreak(String s, List<String> wordDict) {
boolean[] dp = new boolean[s.length()+1];
dp[s.length()] = true;
for(int i=s.length()-1; i>=0; i--)
for(int j=i+1; j<=s.length(); j++) {
if(dp[j] && wordDict.contains(s.substring(i, j))) {
dp[i] = true;
break;
}
}
return dp[0];
}
}
PS:
(1)递归用set memorize的时候可以memorize index
(2)递归+Memorize 复杂度O(N^2),因为index 需要遍历一遍,判断从0 到index i可不可行需要i次查找Set,而index不会减小,一旦遍历到index i,index 之前的直接在Set里面拿
For example, given
s =
"leetcode",
dict =
["leet", "code"].
Return true because
"leetcode"can be segmented as
"leet code".
这是以前刷题写的博客,尼玛刷完就忘了,当时一心想着刷题的数量,到现在就TMD感觉什么都没刷一样,看来刷题应有的姿势是:刷题自是手段,刷的过程中学习别人怎么思考的才是王道,不扯了,总结
第一反应就是递归,很快写出
import java.util.List;
public class Solution {
public boolean wordBreak(String s, List<String> wordDict) {
if("".equals(s)) return true;
for(String t : wordDict) {
if(s.startsWith(t) && wordBreak(s.substring(t.length()), wordDict))
return true;
}
return false;
}
}
TLE没商量,那就用Hash memorize吧
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class recrusion {
Set<String> canBreak = new HashSet<String>();
public boolean wordBreak(String s, List<String> wordDict) {
4000
if("".equals(s) || canBreak.contains(s)) return true;
for(String t : wordDict) {
if(s.startsWith(t) && wordBreak(s.substring(t.length()), wordDict)) {
canBreak.add(s);
return true;
}
}
return false;
}
}
还是TLE,考虑到已经有递归和优化的形式了,为什么不用DP呢?但是这个TMD的递归好像不能划分子问题,即使知道了dp[i]之前的值,好像跟求解dp[i]并没有什么关系,自此就卡主了。‘
那就在Discuss里面看答案吧,我差,有DFS,BFS,DP,为毛老子不行
然后发现:在DFS的时候每一步决策他们看的是String s的index,而不是在dict里面选择一个就继续进行下一步,好,那我改
public class recrusion2 {
Set<String> canBreak = new HashSet<String>();
public boolean wordBreak(String s, List<String> wordDict) {
return dfs(s, 0, wordDict);
}
private boolean dfs(String s, int start, List<String> wordDict) {
if(start == s.length() || canBreak.contains(s.substring(start))) return true;
for(int i=start; i<s.length(); i++) {
if(wordDict.contains(s.substring(start, i+1)) && dfs(s, i+1, wordDict)) {
canBreak.add(s);
return true;
}
}
return false;
}
}
继续TLE,仔细看,发现canBreak这个set根本就没有起到作用,因为他是在return true的时候才会有String被加到里面,这是已经可以确定答案就是true,TMD的还要加个蛋啊
那就弄个cannotBreak的set吧
public class recursion4 {
Set<String> cannotBreak = new HashSet<String>();
public boolean wordBreak(String s, List<String> wordDict) {
return dfs(s, 0, wordDict);
}
private boolean dfs(String s, int start, List<String> wordDict) {
if(start == s.length()) return true;
if(cannotBreak.contains(s.substring(start))) return false;
for(int i=start; i<s.length(); i++) {
if(wordDict.contains(s.substring(start, i+1))) {
if(dfs(s, i+1, wordDict))
return true;
else
cannotBreak.add(s.substring(i+1));
}
}
return false;
}
}
终于AC,划分子结构也挺明了的了,按照递归的反方向DP就OK
import java.util.List;
public class Solution {
public boolean wordBreak(String s, List<String> wordDict) {
boolean[] dp = new boolean[s.length()+1];
dp[s.length()] = true;
for(int i=s.length()-1; i>=0; i--)
for(int j=i+1; j<=s.length(); j++) {
if(dp[j] && wordDict.contains(s.substring(i, j))) {
dp[i] = true;
break;
}
}
return dp[0];
}
}
PS:
(1)递归用set memorize的时候可以memorize index
(2)递归+Memorize 复杂度O(N^2),因为index 需要遍历一遍,判断从0 到index i可不可行需要i次查找Set,而index不会减小,一旦遍历到index i,index 之前的直接在Set里面拿
相关文章推荐
- leetcode-139-Word Break
- 139. Word Break
- [Leetcode] #139 Word Break
- 139. Word Break
- [leetcode 139] Word Break
- 【LeetCode】139 - Word Break
- [leetcode] 139 Word Break
- LeetCode 139. Word Break
- 139. Word Break(dp)
- 139. Word Break
- 139. Word Break
- leetcode 139. Word Break
- 139. Word Break
- 139. Word Break
- leetcode 139 —— Word Break
- leetcode 139. Word Break
- LeetCode 139. Word Break(单词分隔)
- leetcode 139. Word Break(dp,字典匹配)
- 139. Word Break
- Leetcode题解 - 139. Word Break