- 题目
给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。
- 说明
拆分时可以重复使用字典中的单词。
你可以假设字典中没有重复的单词。
分析:
最暴力的想法是直接搜索,枚举每一段看看是否有对应的单词,复杂度O(2^n)
采用动态规划的方法:
- 状态表示:
f[i]
表示前i个字符是否可以拆分成字典中的单词 - 状态转移:如果
1 ~ i
之间的某个位置j
可以满足f[j] = true
并且j + 1 ~ i
这一段是一个单词,那么f[i]
就是真
class Solution {
Map<String, Boolean> map = new HashMap<>();
public boolean wordBreak(String s, List<String> wordDict) {
wordDict.forEach((word) -> map.put(word, true));
int n = s.length();
boolean f[] = new boolean[n + 1];
f[0] = true;
s = " " + s;
for (int i = 1; i <= n; i ++ ) {
for (int j = 1; j <= i; j ++ ) {
if (f[j - 1] && map.containsKey(s.substring(j, i + 1))) {
f[i] = true;
break;
}
}
}
return f[n];
}
}
这里的复杂度其实是
O(n^3)
的,因为截取字符串这个操作是O(n)
的,可以手写哈希表或者trie树,将复杂度优化为O(n^2)