139. 单词拆分。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
 

提示:

1 <= s.length <= 300
1 <= wordDict.length <= 1000
1 <= wordDict[i].length <= 20
s 和 wordDict[i] 仅有小写英文字母组成
wordDict 中的所有字符串 互不相同

解题思路:

翻译题目可以理解为能不能找出wordDict中的词的一种排列,使这个排列与s相同。这里之所以说的是排列不是组合,是因为wordDict同一堆元素的组合只能取到一种,而s可能对应这些元素的另一种组合,这样就会漏算。比如,s = [2, 1],wordDict = [1, 2]如果取组合的话,wordDict可能只能取到[1, 2]这一种组合(3个元素的组合),显然这个组合与s并不相同(顺序不同);但如果讨论的是排列数,那么wordDict就可取到[1, 2],[2, 1],这样第二项就可以跟s匹配了

从wordDict中找到特定元素放到一起,且这些元素满足一定的条件,这样的描述满足背包问题的特征。容量是字符串的长度,物品是字典,每件物品可重复取,所以是完全背包。dp[j]表示字符串到长度j可不可被拆分,true or false。

这里说一下求组合数量得先遍历物品再遍历容量的原因:

假设dp[0]=1,dp[1]=3。那么先遍历物品再遍历容量的话就只能先到取1,再取3,只能取到{1, 3}这个组合,而不能取到{3, 1}这个组合。即dp[4]中对于1和3就只有{1, 3}这种情况

再说一下求排列数量得先遍历容量再遍历容物品的原因:

假设dp[0]=1,dp[1]=3。那么先遍历容量再遍历物品的话每个容量都要经过1和3的计算,即会先对取1的情况进行决策(可以取到{1, 3}),再对取3的情况进行决策(可以取到{3, 1})。即dp[4]中对于1和3有{1, 3}和{3, 1}2种情况.

dp四部曲:

确定dp数组:dp[j]表示字符串到长度j可不可被拆分,true or false

确定递推关系dp[j] =dp[j] or (dp[j - len(dict[i])] and word[j - len(dict[i]) : j]==dict[i])

初始化dp数组:dp[0] =true,只是为了推导方便,因为其他dp都是从dp[0]推过去的,其他为false

遍历顺序:由于讨论的是排列,所以外层遍历容量(s),内层遍历物品(wordDict),均采用顺序遍历

代码如下:

class Solution:
    def wordBreak(self, s: str, wordDict: List[str]) -> bool:
 
        dp = [False] * (len(s) + 1)
        dp[0] = True
        for j in range(len(s) + 1):
            for word in wordDict:
                if(j >= len(word)):
                    dp[j] = dp[j] or (dp[j - len(word)] and s[j - len(word) : j] == word)
        return dp[len(s)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

翔空中,策人生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值