题目:
给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。
说明:
- 拆分时可以重复使用字典中的单词。
- 你可以假设字典中没有重复的单词。
示例 1:
输入: s = "leetcode", wordDict = ["leet", "code"] 输出: true 解释: 返回 true 因为 "leetcode" 可以被拆分成 "leet code"。
示例 2:
输入: s = "applepenapple", wordDict = ["apple", "pen"] 输出: true 解释: 返回 true 因为"
applepenapple"
可以被拆分成"
apple pen apple"
。 注意你可以重复使用字典中的单词。
示例 3:
输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"] 输出: false
思路:
利用动态规划求解。如果我知道给定字符串的0到i子串可以用字典中的单词表达,那么我只需要知道i+1到末尾的子串能否被字典表达即可知道整个字符串能否被字典表达。所以随着i的增大,问题规模逐渐的缩小,且之前求解过的结果可以为接下来的求解提供帮助,这就是动态规划了。设dp[i]代表s.substring(0, i)能否被字典表达,此刻我们知道dp[0]~dp[i-1]的结果。而dp[i]的结果由两部分组成,一部分是dp[j](j < i),已知;另一部分是j到i之间的字符串是不是在字典里。当这两个部分都为真的时候,dp[i]即为真。而一旦dp[i]为真,就不用继续迭代了。测试的时候发现倒着遍历会比正着遍历速度稍稍快一点,大概是因为test case的字典里长度较长的单词要比长度较短的单词多。
java代码:
class Solution {
public boolean wordBreak(String s, List<String> wordDict) {
boolean[] dp = new boolean[s.length() + 1];
dp[0] = true;
for (int i = 1; i <= s.length(); i++) {
for (int j = i - 1; j >= 0 && !dp[i]; j--) {
String check = s.substring(j, i);
dp[i] = dp[j] && wordDict.contains(check);
}
}
return dp[s.length()];
}
}
由于水平有限,文章中难免会有一些错误,有纰漏之处恳请各位大佬不吝赐教!
及时更新最新文章和学习资料,一起来学习: