单词拆分
给定一个非空字符串 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
方法一:暴力递归(超时)
public boolean wordBreak(String s, List<String> wordDict) {
return wordBreak(s, wordDict, 0);
}
public boolean wordBreak(String s, List<String> wordDict, int i) {
if (s.isEmpty()) {
return true;
}
for (int j = 0; j < s.length(); j++) {
if (wordDict.contains(s.substring(0, j + 1)) && wordBreak(s.substring(j + 1), wordDict, i + 1)) {
return true;
}
}
return false;
}
记忆优化
public boolean wordBreak(String s, List<String> wordDict) {
int[] dp = new int[s.length()];
return wordBreak(s, wordDict, 0, 0, dp);
}
public boolean wordBreak(String s, List<String> wordDict, int i, int index, int[] dp) {
if (index == s.length()) {
return true;
}
if (dp[index] != 0) {
return dp[index] == 1;
}
for (int j = index; j < s.length(); j++) {
if (wordDict.contains(s.substring(index, j + 1)) && wordBreak(s, wordDict, i + 1, j + 1, dp)) {
dp[index] = 1;
return true;
}
}
dp[index] = -1;
return false;
}
动态规划
public boolean wordBreak(String s, List<String> wordDict) {
boolean[] dp = new boolean[s.length()];
for (int i = 0; i < s.length(); i++) {
for (int j = i; j >= 0; j--) {
if (j == 0 && wordDict.contains(s.substring(0, i + 1))) { //空串
dp[i] = true;
} else if (dp[j] && wordDict.contains(s.substring(j + 1, i + 1))) {
dp[i] = true;
break;
}
}
}
return dp[s.length() - 1];
}