LeetCode 热题 HOT 100 第四十五天 139. 单词拆分 中等题 用python3求解

题目地址

给你一个字符串 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中的所有字符串互不相同

在这里插入图片描述
此题属于背包问题

解法:动态规划
在这里插入图片描述

1.初始化 dp=[False,False,⋯,False],长度为n+1。n为字符串长度。dp[i]表示s的前i位是否可以用wordDict中的单词表示。

2.初始化dp[0]=True,空字符可以被表示。

3.遍历字符串的所有子串,遍历开始索引i,遍历区间 [0,n):
遍历结束索引j,遍历区间[i+1,n+1):
若dp[i]=True且s[i,⋯,j)在wordlist中:dp[j]=True。
解释:dp[i]=True说明s的前i位可以用wordDict表示,则s**[i,⋯,j)出现在wordDict中,说明s的前j位可以表示**。

4.返回dp[n]

复杂度分析:
时间复杂度:O(n^2)
空间复杂度:O(n)

代码实现:

class Solution:
    def wordBreak(self, s: str, wordDict: List[str]) -> bool:       
        n=len(s)
        dp=[False]*(n+1) # 初始化dp=[False,...,False],长度为n+1,n为字符串长度。dp[i]表示s的前i位是否可以用wordDict中的单词表示。
        dp[0]=True # 初始化dp[0]=True,空字符串可以被表示
        for i in range(n):
            for j in range(i+1,n+1):
                if(dp[i] and (s[i:j] in wordDict)):
                    print('i:',i)
                    print('j:',j)
                    print('s[i:j]:',s[i:j])
                    dp[j]=True
        return dp[-1]  # dp[n]和dp[-1]是一样的

类完全背包问题:s->背包 wordDict->物品
1.状态定义:dp[i]为考虑wordDict所有物品是否能凑成s[0,i-1]
2.状态转移:考虑新的s[i-1],其转移为true的途径为dp[j],其中j=[0,i-1]
若dp[j]为true(说明s[0,j-1]可以凑成)并且,s[j,i-1]存在于wordDict中,就可以转移为true
3.初始化:dp[0]=true,否则后面的永远也凑不成;而除了dp[0]其余均为false,说明没转移到就是凑不成为false
4.遍历顺序:这里只是要求能否凑成,因此背包容量与物品的遍历顺序无所谓,但是容量遍历必须正序
但是若先遍历物品则转移后的状态不符合dp[i]的定义(考虑所有的物品)
因此要先遍历背包容量,再遍历物品;同时这里不是单纯遍历物品,而是遍历前面状态是否转移过来
因此是遍历s的前面的分割线j∈[0,i-1]
5.返回形式:返回dp[n]就是所求

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值