问题描述:
给定一个非空字符串s
和一个包含非空单词列表的字典wordDict
,判定s
是否可以被空格拆分为一个或多个在字典中出现的单词。
说明:
- 拆分时可以重复使用字典中的单词。
- 你可以假设字典中没有重复的单词。
示例 :
输入: s = “leetcode”, wordDict = [“leet”, “code”]
输出: true
解释: 返回 true 因为 “leetcode” 可以被拆分成 “leet code”。
问题分析:
这个题目很容易想到方法就是广度优先或者深度优先来做,看了题目分类,人家是动态规划,所以现在,介绍一种动态规划的方法。要判断s
是否可以被拆分,可以先倒着分析,假设它可以被拆分,从字符串s
由后向前看,后面拆分,一定是在前面被拆分的基础上完成。所以具体思路如下:
(1)设dp[i]
表示字符串s[0:i]
是否可以被拆分,False
不能,True
能。
(2)现在要想求dp[i]
的值,很显然只要判断dp[i - l]
的值和子串s[i - l: i]
是否存在wordDict
中,其中l
为wordDict
中一个单词的长度,所以在这一块,可以遍历所有的单词来求。
(3)可以先求出wordDict
中每个长度,并且给它排序,方便后面的计算。
Python实现:
class Solution:
def wordBreak(self, s, wordDict):
words = set(wordDict) # 去重
lengths = sorted({len(w) for w in words}) # 从小到大排序
n = len(s)
dp = [False] * (n + 1) # 初始化dp
dp[0] = True
for i in range(1, n + 1):
for l in lengths: # 选择单词依次判断
if not dp[i] and i - l >= 0:
dp[i] = (dp[i - l] and s[i - l: i] in words)
return dp[-1]
if __name__ == '__main__':
solu = Solution()
s, wordDict = "applepenapple", ["apple", "pen"]
print(solu.wordBreak(s, wordDict))
声明: 总结学习,有问题或不妥之处,可以批评指正哦。
题目链接、参考了他人提交的版本。