题目:单词拆分 II
给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,在字符串中增加空格来构建一个句子,使得句子中所有的单词都在词典中。返回所有这些可能的句子。
说明:
示例 :
输入:
s = "pineapplepenapple"
wordDict = ["apple", "pen", "applepen", "pine", "pineapple"]
输出:
["pine apple pen apple",
"pineapple pen apple",
"pine applepen apple"]
解释: 注意你可以重复使用字典中的单词。
----------------------------------------------------------------------------
思路:
很明显需要使用递归的方法。而且必须使用字典保存已经能切分的方式,否则,递归的时间复杂度太高。定义一个函数dfs,表示字符串能被字典中的元素构成的所有构造方式。所以,问题转化成了递归分段求解当前字符串能够被分割的问题,如果可以,就拼接后面的分割部分。否则就返回空字符串。
解法1:直接递归处理,超时。
解法2#: 递归+构建额外字典保存切分结果
class Solution(object):
def wordBreak(self, s, wordDict):
"""
:type s: str
:type wordDict: List[str]
:rtype: List[str]
"""
res = []
memo = dict()
return self.dfs(s, res, wordDict, memo)
def dfs(self, s, res, wordDict, memo):
# 如果当前单词存在于字典中,直接返回
if s in memo:
return memo[s]
# 当前字符串的为空判断
if not s:
return [""]
# 拼接存在于字典中的字符串
res = []
for word in wordDict:
if s[:len(word)] != word:
continue
for r in self.dfs(s[len(word):], res, wordDict, memo):
res.append(word + ("" if not r else " " + r))
memo[s] = res
return res
解法3:设置一个动态的数组dp[] 这个数组保存的是之前的单词是否能够组成单词,之前没有使用动态规划,导致s中出现重叠的情况是,就不能很好的分词,这个代码的思路是对s进行遍历,判断条件是如果s[:i+1]也就是s的前i+1个字符在dict中出现,并且dp[i] == 1的话,说明这个单词有效,代码如下。
所以总的时间复杂度是O(n^2)(i的累加仍然是n^2量级),而空间复杂度则是字符串的数量,即O(n)。
class Solution:
def wordBreak(self, s, wordDict):
"""
:type s: str
:type wordDict: List[str]
:rtype: bool
"""
if s == '':
return True
if len(wordDict) == 1:
if s == wordDict[0]:
return True
else:
return False
# 构建dp:0/1数组,用于记录s中每个元素的匹配状态
dp = [0 for _ in range(len(s)+1)]
dp [0] = 1
for i in range(len(s)):
str_ = s[:i+1]
for j in range (i+1):
if str_ in wordDict and dp[j]:
dp[i+1] = 1
str_ = str_[1:]
return dp[len(s)] == 1
参考:
https://blog.csdn.net/weixin_41303016/article/details/88320907
https://blog.csdn.net/fuxuemingzhu/article/details/85089275
https://blog.csdn.net/maka_uir/article/details/84817090
https://blog.csdn.net/linhuanmars/article/details/22358863