• 代码随想录day46 | 动态规划P8 | ● 139. ● 多重背包● 背包问题总结


    139.单词拆分 

    思路

    本道是枚举分割所有字符串,判断是否在字典里出现过。可以使用回溯法 / 完全背包解法

    回溯:

    代码随想录第二十七天 | 回溯算法P3 |● 39. ● 40.● 131.-CSDN博客

    之前讲解回溯法专题的时候,讲过的一道题目 lc 131,就是枚举字符串的所有分割情况。

    lc 131 :是枚举分割后的所有子串,判断是否回文。

    本道是枚举分割所有字符串,判断是否在字典里出现过。

    背包:

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

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

    背包五步曲:

            dp[ j ]: 表示 字符串长度为 j , dp [ j ] 为  true 表示其可以拆分为一个或多个字典中的单词

            递推:

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

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

            初始化: 从递推公式中可以看出,dp[i] 的状态依靠 dp[j]是否为true,那么dp[0]就是递推的根基,dp[0]一定要为true,否则递推下去后面都都是false了。其余则均初始化为false, 防止初始值影响递推

            遍历顺序,先背包, 再物品 

    可以看出 i 依赖于 j (j < i) 同时是一个完全背包问题, 从左到右. 问题来了, 先物品 or 先背包?

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

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

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

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

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

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

    代码

    回溯 + 记忆化

    1. class Solution {
    2. private Set set;
    3. private int[] memo;
    4. public boolean wordBreak(String s, List wordDict) {
    5. set = new HashSet(wordDict);
    6. memo = new int [s.length()];
    7. return backtracking(s, 0);
    8. }
    9. public boolean backtracking(String s, int startIndex){
    10. if(startIndex == s.length()){
    11. return true;
    12. }
    13. if(memo[startIndex] == -1) {
    14. return false;
    15. }
    16. for(int i = startIndex; i < s.length(); i++){
    17. //当前拆分的子串为[startIndex, i]
    18. String cur = s.substring(startIndex, i + 1);
    19. //当前子串不存在于字典中
    20. if(set.contains(cur) == false){
    21. continue;
    22. }
    23. //存在了, 进入子问题
    24. if(backtracking(s, i + 1)) return true;
    25. }
    26. // 这里是关键,找遍了startIndex~s.length()也没能完全匹配,标记从startIndex开始不能找到
    27. memo[startIndex] = -1;
    28. return false;
    29. }
    30. }

     完全背包

    1. class Solution {
    2. public boolean wordBreak(String s, List wordDict) {
    3. HashSet set = new HashSet<>(wordDict);
    4. int [] dp = new int [s.length() + 1];
    5. dp[0] = 1;
    6. //先遍历背包
    7. for(int i = 1; i < s.length() + 1; i++){
    8. //再遍历物品
    9. //若当前已经为 1 则 不再修改 / 删去不影响结果
    10. for(int j = 0; j < i && dp[i] == 0; j++){
    11. if(set.contains(s.substring(j, i)) && dp[j] == 1){
    12. dp[i] = 1;
    13. }
    14. }
    15. }
    16. return dp[s.length()] == 1 ? true : false ;
    17. }
    18. }

    多重背包

    背包问题总结篇! 

  • 相关阅读:
    HJ16 购物单
    产品经理懂点技术:几种常用的系统开发方法
    java计算机毕业设计药品销售系统源程序+mysql+系统+lw文档+远程调试
    AttributeError: module ‘tensorflow‘ has no attribute ‘__version__‘
    你真的熟练运用 HTML5 了吗,这10 个酷炫的 H5 特性你会几个?
    Github 2024-03-08 Java开源项目日报 Top10
    windows下的文件路径怎么在pycharm中使用(python)
    中秋实验揭示gin下ShouldBindJSON、ShouldBindWith的json到对象映射程序是怎么跑飞的[Go 避坑必备之良好的编码习惯很重要]
    海森矩阵与多元多项式的结合与极值判定【浅显易懂版:欢迎补充】
    小米秋招卷1
  • 原文地址:https://blog.csdn.net/FhilMs/article/details/138168470