题目描述:
给定一个非空字符串 s
和一个包含非空单词的列表 wordDict
,判定 s
是否可以被空格拆分为一个或多个在字典中出现的单词。
说明:
- 拆分时可以重复使用字典中的单词。
- 你可以假设字典中没有重复的单词。
示例 1:
1 | 输入: s = "leetcode", wordDict = ["leet", "code"] |
示例 2:
1 | 输入: s = "applepenapple", wordDict = ["apple", "pen"] |
示例 3:
1 | 输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"] |
链接:
https://leetcode-cn.com/problems/word-break
题目分析
字典中的单词不会重复,并且可以重复使用,我们可以考虑使用一个哈希表存储这个字典。而对于字符串 s
,我们用动态规划的思想,dp[i]
表示 s
的前 i
个字母 s[0 ~ i-1]
是否可以使用字典中的单词表示,则我们知道,如果 dp[j]
为真,并且 s[j ~ i-1]
刚好是字典中的一个单词,则 dp[i]
也为真。而 dp[0]
作为起始条件,表示空串的结果为真。对于每一个 dp[i]
,我们都要遍历 dp[0] ~ dp[i-1]
,寻找以这个位置分割是否符合条件,一旦符合条件则可以置为真并提前退出遍历。遍历所有的 dp[i]
之后,我们的答案就是 dp[s.size()]
。
1 | class Solution { |
时间复杂度:$O(n^2)$,其中 $n$ 为字符串的长度。动态规划的状态数为 $n+1$,而对于每个状态最多都要枚举 $O(n)$ 个分割点,其实也即双层遍历,时间复杂度为 $O(n^2)$。
空间复杂度:$O(n+k)$,其中 $n、k$ 分别为字符串的长度与字典的大小。动态规划数组大小为 $n+1$,而哈希表大小为 $k$。
PS:这道题还存在优化空间,比如如果字典中的单词量较少,内层循环也可以设计成匹配字典中每个单词的形式;比如可以进行剪枝,内层循环中分割的位置无需从 0
开始,可以从字典中最长的单词长度作为右半部分开始。