算法训练营第四十六天|139.单词拆分、背包问题小总结

73 阅读3分钟

139. 单词拆分

class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        HashSet<String> set = new HashSet<>(wordDict);
        // dp[i] : 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词。
        boolean[] dp = new boolean[s.length() + 1];
        dp[0] = true;

        for(int i = 1; i <= s.length(); i++){
            for(int j = 0; j < i && !dp[i]; j++){
                if(set.contains(s.substring(j, i)) && dp[j])dp[i] = true;
            }
        }

        return dp[s.length()];
    }
}

0-1背包和完全背包总结

动规五步:

  • 确定dp数组以及下标的含义
  • 确定递推公式
  • 确定dp数组如何初始化
  • 确定遍历顺序
  • 举例推导dp数组

递推公式的确定

问能否能装满背包(或者最多装多少):dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);, 有的题目中 weight 和 value 是同一个数组,则对应为dp[j] = Math.max(dp[j], dp[j - nums[i]] + nums[i]),对应题目如下:

问装满背包有几种方法:dp[j] += dp[j - nums[i]];,对应题目如下:

问背包装满的最大价值:dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);,对应题目如下:

问装满背包所有物品的最小个数:dp[j] = Math.min(dp[j - weight[i]] + 1, dp[j]);,对应题目如下:

遍历顺序的确定

0-1背包

以二维数组遍历0-1背包问题,先遍历物品再遍历背包或者先遍历背包再遍历物品都是可以的,并且内层循环可以从前向后遍历。

以一维数组遍历0-1背包问题,只能先遍历物品再遍历背包,并且内层只能从后向前遍历,目的是确保每个物品只会被装入一次,不会被重复使用。

完全背包

纯完全背包问题:二维数组或一位数组遍历完全背包问题,先遍历物品或是先遍历背包都是可以的。并且内层循环从前往后遍历。

组合数问题:外层for遍历物品,内层for遍历背包。物品在结果集合中的顺序无影响。

排列数问题:外层for遍历背包,内层for遍历物品。物品在结果集合中的顺序有影响。

相关题目如下:

求最小数:两层for循环的先后顺序无所谓了。相关题目如下: 求最小数:动态规划:322. 零钱兑换动态规划:279.完全平方数