day46

1、leetcode139 单词拆分

  1. 问题分析==》完全背包问题

    • 背包:字符串s
    • 物品:字典中的字符串(每个字符串可重复使用)
  2. 动规五步法

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

    2. 递归公式

      if dp[j]==true && s[i,j] in 字典]:
      	dp[i] = true
      
    3. 初始化

      • dp[i] 由前一个状态推出 =====》dp[0] = true
    4. 确定遍历顺序

      • 要求字典中的字符串要按照一定顺序排列,才能组成字符串s ===》求排列数
      • 因此,先遍历背包,再遍历物品
    5. 举例推导dp[i]

  3. 代码

    class Solution {
        public boolean wordBreak(String s, List<String> wordDict) {
            boolean[] dp = new boolean[s.length() + 1];
            dp[0] = true;
    
            for(int j=1; j<=s.length(); j++) {//先遍历背包
                for(int i=0; i<j ; i++) {//再遍历物品
                    if(dp[i]==true && wordDict.contains(s.substring(i, j))) {
                        dp[j] = true;
                    }
                }
            }
    
            return dp[s.length()];
    
        }
    }
    

2、背包总结

  1. 背包递推公式
    1. 问能否能装满背包(或者最多装多少):dp[j] = max(dp[j], dp[j - nums[i]]+nums(i))
    2. 问装满背包有几种方法: dp[j] += dp[j-nums[i]]
    3. 问背包装满最大价值:dp[j] = max(dp[j], dp[j - weight[i]] + value[i])
    4. 问装满背包所有物品的最小个数:dp[j] = min(dp[j - coins[i]] + 1, dp[j]);
  2. 背包顺序
    1. 01背包
      1. 二维dp数组
        • 先遍历物品还是先遍历背包都是可以的,且第二层for循环是从小到大遍历。
      2. 一维背包数组(滚动数组)
        • 只能先遍历物品再遍历背包容量,且第二层for循环是从大到小遍历。
    2. 完全背包
      • 一维背包数组
        • 先遍历物品还是先遍历背包都是可以的,且第二层for循环是从小到大遍历。
          • 先遍历物品,再遍历背包 ===》 组合数
          • 先遍历背包,再遍历物品 ===》 排列数
        • 若求最小数,则两层for循环的先后顺序就无所谓了
posted @ 2023-03-01 21:26  黄三七  阅读(28)  评论(0)    收藏  举报