dp--139. 单词拆分/medium 理解度B

文章介绍了如何利用动态规划方法判断给定字符串s是否可以通过字典中的单词拼接而成,通过定义状态、检查重复子问题和最优子结构来解决该问题。示例和代码展示了如何实现这一过程。
摘要由CSDN通过智能技术生成

1、题目

给你一个字符串 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
  • swordDict[i] 仅由小写英文字母组成
  • wordDict 中的所有字符串 互不相同
Related Topics
  • 字典树
  • 记忆化搜索
  • 数组
  • 哈希表
  • 字符串
  • 动态规划

2、题目分析

动态规划核心用处是求最值,当然也可用于判断是否存在可行性方案这类的问题。因为是先有多个可行性方案,才会衍生出最值问题。
故该问题也可以用动态规划,虽然题目只求截止到最后一个字母,字典中出现的单词是否能拼接出该字母及前面所组成的字符串 s。

动态规划的解决套路可分为 2 步,①基于问题能定义出状态,②状态间具备动态规划的三个特性

①基于问题定义出状态:问题是“求截止到最后一个字母所组成的字符串,是否可由字典拼接而成”。则状态就可以定义为“截止到某个字母所组成的字符串,是否可由字典拼接而成”。因为这样,当流转到最终状态时,即可得到问题的答案。

②状态间具备动态规划的三个特性

  1. 重复子问题且重复策略
    重复子问题:截止到每个字母,问题都是“字典中出现的单词是否能拼接出截止到该字母所组成的字符串”
  2. 最优子结构
    重复策略&最优子结构:针对每个子问题,策略都是以该字母做为尾字符,匹配字典中的每个单词,然后往前推到该单词加入前的状态,若单词加入前的状态已被求得解。则当前状态就有解。否则,当前状态也无解。
  3. 无后效性
    更前的状态不影响当前状态:从2、最优子结构可知,我们求当前状态时,只关注单词加入前的状态,而无需关注单词加入前的状态是如何被一步步推导出来的。
    后面的状态不影响当前状态:从2、最优子结构可知,当前状态完全有前面的状态转移得到,跟后面的状态没有关系

3、解题步骤

1、dp[i] 表示截止到第 i 个字符,所组成的字符串,是否可由字典拼接而成。
2、初始化,dp[0]表示空串,默认可由字典拼接而成
3、迭代处理截止到的每个字符所组成的字符串,判断字符串是否可由字典拼接而成
4、判断当前状态是否可达。即是否存在前面的某个状态,结合上本单词 word,转移到当前状态
5、若以当前字符为尾字符,在字典中找到了匹配字符串的后缀。再因为开头已经判断了结合该单词前的那个状态dp值为1,即前面状态可达,故当前状态可达。

4、复杂度最优解代码示例

    public boolean wordBreak(String s, List<String> wordDict) {
        // 1、dp[i] 表示截止到第 i 个字符,所组成的字符串,是否可由字典拼接而成。
        boolean[] dp = new boolean[s.length() + 1];
        // 2、初始化,dp[0]表示空串,默认可由字典拼接而成
        dp[0] = true;
        for (int i = 1; i <= s.length(); i++) {
            // 3、迭代处理截止到的每个字符所组成的字符串,判断字符串是否可由字典拼接而成
            for (String word : wordDict) {
                // 4、判断当前状态是否可达。即是否存在前面的某个状态,结合上本单词 word,转移到当前状态
                if (i >= word.length() && dp[i - word.length()] && s.startsWith(word, i - word.length())) {
                    dp[i] = true;
                    break;
                }
            }
        }
        return dp[s.length()];
    }

5、抽象与扩展

通用动态规划的解法,见标题二

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值