dp数组,记忆化数组
题目
给定一个非空字符串 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
题解
方法一:动态规划
思路和算法

初始化 $dp=[False,\cdots,False]$,长度为 n+1。n 为字符串长度。$dp[i]$ 表示 s 的前 i 位是否可以用 wordDict中的单词表示。
初始化 $dp[0]=True$,空字符可以被表示。
遍历字符串的所有子串,遍历开始索引 i,遍历区间$ [0,n)$:
- 遍历结束索引 j,遍历区间 $[i+1,n+1)$:
- 若 $dp[i]=True$且 $s[i,\cdots,j)$ 在 wordlist 中:$dp[j]=True$
解释:$dp[i]=True$说明s 的前 i位可以用 wordDict 表示,则$ s[i,\cdots,j)$出现在 wordDict 中,说明 s 的前 j位可以表示。
- 若 $dp[i]=True$且 $s[i,\cdots,j)$ 在 wordlist 中:$dp[j]=True$
- 遍历结束索引 j,遍历区间 $[i+1,n+1)$:
返回 $dp[n]$
复杂度分析
- 时间复杂度:$O(n^2)$
- 空间复杂度:$O(n)$
1 | class Solution: |
1 | a= Solution() |
True
1 | a= Solution() |
True
1 | a= Solution() |
[True, False, False, True, True, False, False, True, False, False]
False
方法二:记忆化回溯
- 使用记忆化函数,保存出现过的 backtrack(s),避免重复计算。
- 定义回溯函数 backtrack(s)
- 若 s 长度为 0,则返回 True,表示已经使用 wordDict中的单词分割完。
- 初始化当前字符串是否可以被分割 res=False
- 遍历结束索引 i,遍历区间 [1,n+1):
- 若 $s[0,\cdots,i-1]$在 wordDict中:$res=backtrack(s[i,\cdots,n-1])\ or\ res$。
解释:保存遍历结束索引中,可以使字符串切割完成的情况。
- 若 $s[0,\cdots,i-1]$在 wordDict中:$res=backtrack(s[i,\cdots,n-1])\ or\ res$。
- 返回 resres
- 返回 backtrack(s)
1 | class Solution: |
False