人生的大起大落就在一瞬间:吃完饭回来看到粉丝+1并为此开心,过了几分钟再看就没有了。
另外下午真的是诸事不宜啥也不想学的时间段。(这题直接先看题解吧
1.题目
2.分析
转移方程:
dp[i]表示字符串的前i个字符能否成功拆分,需要枚举s[0…i-1]中的分割点j,看s[0…j-1]和s[j…i-1]能否成功拆分。而s[0…j-1]正是dp[j]。
边界条件:
dp[0]=true,表示空串且合法
check的实现:检查一个字符串是否出现在给定的字符串列表里一般可以考虑哈希表来快速判断。
剪枝优化:
剪枝,枚举分割点的时候倒着枚举,如果分割点 j 到 i -1的长度已经大于字典列表里最长的单词的长度,那么就结束枚举。
3.代码
class Solution {
public boolean wordBreak(String s, List<String> wordDict) {
HashSet<String> set=new HashSet<>(wordDict);
int len=s.length();
boolean[] dp=new boolean[len+1];
dp[0]=true;
//找到set中最长单词的长度
int maxw=0;
for(String c:set){
maxw=Math.max(maxw,c.length());
}
for(int i=1;i<=len;i++){//从0位置开始,长度为i的字符串
for(int j=i-1;j>=0&&j>=i-maxw;j--){// i-1-j+1=i-j是右边部分的长度,如果超出最长单词长度就不用看了
//dp[j]:[0,j-1]
//substring(j,i): [j,i-1]
if(dp[j]&&set.contains(s.substring(j,i))){
dp[i]=true;//说明长度为i成功了,继续验证下一个长度,回到外层循环
break;
}
}
}
return dp[len];
}
}
4.复杂度
时间复杂度:O(n²) ,其中 n 为字符串 s 的长度。我们一共有O(n)个状态需要计算,每次计算需要枚举O(n)个分割点,哈希表判断一个字符串是否出现在给定的字符串列表需要O(1)的时间,因此总时间复杂度为 O(n²)。
空间复杂度:O(n),其中 n为字符串 s 的长度。我们需要O(n) 的空间存放dp 值以及哈希表亦需要 O(n)的空间复杂度,因此总空间复杂度为 O(n)。