二刷。
牛逼,二刷上来就是backtrack,TLE,时间应该是指数级别的。。
看一刷说的是DP,才想起来。
正好又学习巩固了一下DP。感觉DP套路太多了,每道题都不一样,至少LC上是这样的,很难说总结出什么规律。
按照CodeGanker的路子来:
1.确定可以保存的信息
2.递推式(以及如何在递推中使用保存的信息)
3.确定起始条件
放到这个题说
S能拆成功的话,说明
s.substring(0,i)能拆成功,然后 s.substring(i)是一个在字典中的单词。
后者是一步check: dict.contains(s.substring(i));
前者是需要记录的信息dp[i]表示可拆
然后从头撸一遍就行了
public class Solution {
public boolean wordBreak(String s, Set<String> wordDict) {
if (s.length() == 0) return false;
boolean[] dp = new boolean[s.length()+1];
dp[0] = true;
//dp[i] true s.substring(i) true
for (int i = 0; i < s.length()+1; i++) {
for (int j = 0; j < i; j++) {
if (dp[j] && wordDict.contains(s.substring(j,i))){
dp[i] = true;
break;
}
}
}
return dp[s.length()];
}
}
三刷。
DP做,mem记录从最左边开始的substring可不可分。
dp[0]代表“”永远可分。
edge case要弄对,substring的坐标和遍历的坐标是不一样的= =一开始搞混乱了,说白了还是没完全理解。
public class Solution {
public boolean wordBreak(String s, Set<String> wordDict) {
if (s.length() == 0) return false;
boolean[] dp = new boolean[s.length() + 1];
dp[0] = true;
for (int i = 1; i < dp.length; i++) {
for (int j = 0; j < i; j++) {
if (dp[j] && wordDict.contains(s.substring(j, i))) {
dp[i] = true;
break;
}
}
}
return dp[s.length()];
}
}