代码随想录算法训练营第四十六天 | 139.单词拆分 & 关于多重背包,你该了解这些! & 背包问题总结篇!

139.单词拆分

🔗题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

💡解题思路:动态规划

单词就是物品,字符串s就是背包,单词能否组成字符串s,就是问物品能不能把背包装满。

拆分时可以重复使用字典中的单词,说明就是一个完全背包!

动规五部曲分析如下:

1.确定dp数组以及下标的含义

dp[i] : 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词

2.确定递推公式

如果确定dp[j] 是true,且 [j, i] 这个区间的子串出现在字典里,那么dp[i]一定是true。(j < i )。

所以递推公式是 if([j, i] 这个区间的子串出现在字典里 && dp[j]是true) 那么 dp[i] = true。

3.dp数组如何初始化

从递推公式中可以看出,dp[i] 的状态依靠 dp[j]是否为true,那么dp[0]就是递推的根基,dp[0]一定要为true,否则递推下去后面都都是false了。

那么dp[0]有没有意义呢?

dp[0]表示如果字符串为空的话,说明出现在字典里。

但题目中说了"给定一个非空字符串 s" 所以测试数据中不会出现i为0的情况,那么dp[0]初始为true完全就是为了推导公式。

下标非0的dp[i]初始化为false,只要没有被覆盖说明都是不可拆分为一个或多个在字典中出现的单词。

4.确定遍历顺序

题目中说是拆分为一个或多个在字典中出现的单词,所以这是完全背包。

还要讨论两层for循环的前后顺序。

如果求组合数就是外层for循环遍历物品,内层for遍历背包

如果求排列数就是外层for遍历背包,内层for循环遍历物品

本题其实我们求的是排列数,为什么呢。 拿 s = "applepenapple", wordDict = ["apple", "pen"] 举例。

"apple", "pen" 是物品,那么我们要求 物品的组合一定是 "apple" + "pen" + "apple" 才能组成 "applepenapple"。

"apple" + "apple" + "pen" 或者 "pen" + "apple" + "apple" 是不可以的,那么我们就是强调物品之间顺序。

所以说,本题一定是 先遍历 背包,再遍历物品。

5.举例推导dp[i]

以输入: s = "leetcode", wordDict = ["leet", "code"]为例,dp状态如图:

dp[s.size()]就是最终结果。

代码如下:

java 复制代码
public boolean wordBreak(String s, List<String> wordDict) {
        boolean[] dp = new boolean[s.length() + 1];
        dp[0] = true;

        //排列------先遍历背包,再遍历物品
        for (int i = 1; i <= s.length(); i++) {
            for (String word: wordDict) {
                int len = word.length();
                if (i >= len && dp[i - len] && word.equals(s.substring(i - len, i))) {
                    dp[i] = true;
                    break;
                }
            }
        }
        return dp[s.length()];
}

关于多重背包,你该了解这些!

代码随想录

背包问题总结篇!

代码随想录

相关推荐
m0_73691910几秒前
C++中的类型标签分发
开发语言·c++·算法
2301_790300967 分钟前
C++与微服务架构
开发语言·c++·算法
重生之我是Java开发战士13 分钟前
【优选算法】前缀和:一二维前缀和,寻找数组的中心下标,除自身以外数组的乘积,和为K的子数组,和可被K整除的子数组,连续数组,矩阵区域和
线性代数·算法·矩阵
梵刹古音16 分钟前
【C语言】 循环结构
c语言·开发语言·算法
皮皮哎哟23 分钟前
冒泡排序与数组传递全解析 一维二维指针数组及二级指针应用指南
c语言·算法·冒泡排序·二维数组·指针数组·传参·二级指针
m0_5613596724 分钟前
C++代码冗余消除
开发语言·c++·算法
近津薪荼35 分钟前
优选算法——滑动窗口1(单调性)
c++·学习·算法
diediedei36 分钟前
嵌入式C++驱动开发
开发语言·c++·算法
燃于AC之乐41 分钟前
《算法实战笔记》第10期:六大算法实战——枚举、贪心、并查集、Kruskal、双指针、区间DP
算法·贪心算法·图论·双指针·区间dp·二进制枚举
diediedei1 小时前
高性能计算通信库
开发语言·c++·算法