代码随想录算法训练营第四十九天 | 139.单词拆分、多重背包、背包问题总结

139.单词拆分

解题思路

1.dp[i]  字符串的长度为i,dp[i]是否可以被组成

2.递推公式

 if( [j,i] && dp[j] =true)   这个ji区间在字典中,并且dp[j] = true

3.初始化

dp[0] = true   在题目中没有定义,但是为了推导,初始为true

非零下标为false

4.遍历循序

装满这个背包,对物品的顺序是有要求的,因此这题是排列

for( i<=s.size() )

  for(j=0 ; j<i ;j ++)

    string word = s.substr(j,i-j);  进行截取

class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
         unordered_set<string> wordSet(wordDict.begin(),wordDict.end());
         vector<bool> dp(s.size()+1,false);
         dp[0] = true;
         for(int j=1 ; j<=s.size();j++)
         {
            for(int i = 0 ; i < j ; i++)
            {
                 string word = s.substr(i,j-i);
                 if(wordSet.find(word) != wordSet.end() && dp[i]==true)
                    dp[j] = true;
            }
         }
         return dp[s.size()];
    }
};

多重背包

和01背包是很相似的

但是这样拆分为01背包很容易超时,因为vector的动态扩容,因此我们只需要再加一层循环,遍历物品个数即可

 背包问题总结

代码随想录

01背包:2维dp为什么可以转换为1维dp? 

1维dp利用的是滚动数组,由于我们2维dp中,dp[i][j]的值都是由上方或者左上方的某一个值推来的,因此只需要两行数据,然后我们可以将上一行数据拷贝存在一行数据中,动态更新即可

01背包:为什么遍历顺序必须是先物品再背包,为什么遍历背包时,需要倒序遍历?

首先,为什么要倒序遍历?因此由二维dp压缩为一维dp可知,一维dp的值是上一行的数值,因此如果我们从左边正序更新,那么就会丢失上一行数据,无法推出这一行的数据。但我们如果从右边倒序遍历,那么左边的值还未更新,因此是上一行数据,可以推出这一行数据

其次,为什么顺序必须物品,再背包?因为只有这样,物品只会被选取1次(更新完数据了,新数据是由旧数据推来的,因此视为1次),如果反一下,先背包再物品,那么就会变成装满这个容量的背包,有哪些物品 

完全背包: 遍历顺序和for循环内部与01背包的不同

与01背包的不同:我们遍历背包时是正序遍历,从weight[i]开始,因为完全背包物品可以使用无数次,每次都是由新数据(一维dp左边的数据推得而来,视为可以使用无数次)推的而来,因此是正序

如果是纯完全背包问题(求最大价值),遍历顺序是可以颠倒的,因为不管是先行还是先列推导,都可以得到左边的数据

但如果题目求得是组合问题,那么就必须先物品再容量:例如先遍历物品1,再遍历物品2,只会出现[1,2]的情况

如果求得是排列问题,那么就必须先容量再物品,因为假如weight[2]>weight[1],那么在容量为3的情况下,就可能出现[2,1]和[1,2]两种不同的组合,因此是排列

背包添加额外限制条件

因为我们平时都是一维dp[j],只有容量一个限制,如果当我们有别的限制,例如有两个维度的容量,或者对选取物品种类个数有要求,那么就dp[j][k],利用二维dp,多加限制 

收获

背包问题结束,继续加油 

  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值