代码随想录算法训练营day46|139.单词拆分,多重背包,背包问题总结篇

139.单词拆分

力扣

思路:背包算法

1. 完全背包:物品是wordDict中的单词,背包是s;

2. dp数组及其下标的含义:dp[i]表示长度为 i 的字符串是否可以被拆分为 wordDict 中的单词;dp[i] = 1表示可以拆分,dp[i] = 0表示不能拆分;

3. 递推公式:当j < i时,若dp[j] = 1,且 [j,i] 区间的子串出现在字典里,那么 dp[i] = 1。

4. 初始化:dp[0] = 1(dp[0]是递推起点),下标非0的 dp[i] 初始化为false,只要没被覆盖,就说明不可拆分。

5. 遍历顺序:求排列数,外层for循环遍历背包,内层for循环遍历物品。

class Solution {
    public boolean wordBreak(String s, List wordDict) {
        HashSet set = new HashSet<>(wordDict);
        int[] dp = new int[s.length()+1];
        dp[0] = 1;
        for(int i=1;i<=s.length();i++){
            for(int j=0;j

思路:回溯法+记忆化递归

使用memo数组保存每次计算的以startIndex为起点的计算结果。如果memo[startIndex]已经被标记,那么直接返回memory[startIndex]的结果。

class Solution {
    private Set set;
    private int[] memo;
    public boolean wordBreak(String s, List wordDict) {
        memo = new int[s.length()];
        set = new HashSet<>(wordDict);
        return backTracking(s,0);
    }
    public boolean backTracking(String s, int startIndex){
        if(startIndex==s.length()) return true;
        if(memo[startIndex]==-1) return false;
        for(int i=startIndex;i

多重背包

多重背包理论基础

1. 问题形式:有N种物品和一个容量为V 的背包。第i种物品最多有Mi件可用,每件耗费的空间是Ci ,价值是Wi 。求将哪些物品装入背包,可使耗费的空间不超过背包容量,且价值总和最大。

2. 思路:转化为01背包问题。每件物品最多有Mi件可用,那就把Mi件摊开,每件的数量是1。

//版本一:改变物品数量为01背包格式
public void testMultiPack1(){
    List weight = new ArrayList<>(Arrays.asList(1, 3, 4));
    List value = new ArrayList<>(Arrays.asList(15, 20, 30));
    List nums = new ArrayList<>(Arrays.asList(2, 3, 2));
    int bagWeight = 10;
    for (int i = 0; i < nums.size(); i++) {
        while (nums.get(i) > 1) { //把物品展开为i
            weight.add(weight.get(i));
            value.add(value.get(i));
            nums.set(i, nums.get(i) - 1);
        }
    }
    int[] dp = new int[bagWeight + 1];
    for(int i = 0; i < weight.size(); i++) { //遍历物品
        for(int j = bagWeight; j >= weight.get(i); j--) { //遍历背包容量
            dp[j] = Math.max(dp[j], dp[j - weight.get(i)] + value.get(i));
        }
        System.out.println(Arrays.toString(dp));
    }
}
public void testMultiPack2(){
    int[] weight = {1, 3, 4};
    int[] value = {15, 20, 30};
    int[] nums = {2, 3, 2};
    int bagWeight = 10;
    int[] dp = new int[bagWeight + 1];
    for(int i = 0; i < weight.length; i++) { //遍历物品
        for(int j = bagWeight; j >= weight[i]; j--) { //遍历背包容量
            //遍历个数
            for (int k = 1; k <= nums[i] && (j - k * weight[i]) >= 0; k++) {
                dp[j] = Math.max(dp[j], dp[j - k * weight[i]] + k * value[i]);
            }
            System.out.println(Arrays.toString(dp));
        }
    }
}

背包问题总结篇

​​​​​​背包总结篇​​​​​​

 背包递推公式:

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-nums[i]]+value[i]);

4. 装满背包的最小物品数目:dp[j] = min(dp[j-coins[i]]+1, dp[j]);

遍历顺序:

1. 01背包:

(1)二维dp数组,先遍历物品再遍历背包,或者先遍历背包再遍历物品都可以,且第二层for循环从小到大;

(2)一维dp数组,只能先遍历物品再遍历背包容量,且第二层for循环从大到小;

2. 完全背包:

(1)纯完全背包,先遍历物品或先遍历背包都可以,且第二层for循环从小到大。

(2)求组合数,外层for循环遍历物品,内层for遍历背包。

(3)求排列数,外层for遍历背包,内层for循环遍历物品。

你可能感兴趣的:(leetcode,算法,职场和发展)