力扣爆刷第127天之动态规划五连刷(整数拆分、一和零、背包)

力扣爆刷第127天之动态规划五连刷(整数拆分、一和零、背包)

关于0 1 背包问题的总结

背包问题:一维数组,dp[j] = Math.max(dp[j], dp[j-nums[i]] + nums[i])。

01背包遍历顺序:

先物品后背包,物品正序,背包逆序。

如若背包正序则会出现同一个物品重复放入,如物品1重量为1,背包空间为1时放入了,背包空间为2时又放入了。
如果先背包后物品,为了避免重复放入背包依然是逆序,背包容量固定时,每种背包容量只能放入一个物品,即为最大的物品,小的物品都放不进来或者被覆盖了。

求组合数排列数:dp[j] += dp[j - nums[i]]

完全背包遍历顺序:

物品背包没有先后顺序,物品背包都是正序。因为同一个物品不限量可以放入多次,在背包采用正序中。

完全背包求组合数,物品在外,背包在内。求排列数,背包在外,物品在内。

一、343. 整数拆分

题目链接:https://leetcode.cn/problems/integer-break/description/
思路:整数拆分是把整数拆分成k个数使其乘积最大,最低是拆分成两个数,根据题目要求的目标定义dp[i]表示i被拆分后相乘的最大值,对于任意一个数来说,最低是拆分成两个数,然后就是两个数以上,我们要求的就是这些情况中的最大值,显然发现是有状态转移的关系的,如dp[i],如果拆分成两个数,那就是(i-j)* j,如果拆分成两个数以上就是dp[i-j] * j,每一个数都要遍历这些情况,故 dp[i] = Math.max(Math.max(dp[i-j] * j, (i-j)*j), dp[i]);

class Solution {
    public int integerBreak(int n) {
        int[] dp = new int[n+1];
        dp[2] = 1;
        for(int i = 3; i <= n; i++) {
            for(int j = 1; j <= i/2; j++) {
                dp[i] = Math.max(Math.max(dp[i-j] * j, (i-j)*j), dp[i]);
            } 
        } 
        return dp[n];
    }
}

二、96. 不同的二叉搜索树

题目链接:https://leetcode.cn/problems/unique-binary-search-trees/
思路:做动态规划的题目主要是找出重叠子问题,推导出状态转移方程,定义dp[i]表示i个节点的二叉搜索树有多少种结构类型,dp[3]也就是有3个节点我们可以看出,1为根节点有两种,2为根节点有1种,3为根节点有2种,但1为根节点时,右子树有两个节点,这2个节点的种类数量其实是和dp[2]是一样的,由此我们是可以看出关系来的,有N个节点的二叉搜索树的类型数量就等于1-N每一个数字作为根节点时种类数量的累加,这里正好有重叠子问题。故递推公式为dp[i] += dp[j-1] * dp[i-j];
以dp[3]推导举例:
1为根节点,dp[0]*dp[2]。
2为根节点,dp[1]*dp[1]。
3为根节点,dp[2]*dp[0]。这里是有复用关系的。
在这里插入图片描述

class Solution {
    public int numTrees(int n) {
        int[] dp = new int[n+1];
        dp[0] = 1;
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= i; j++) {
                dp[i] += dp[j-1] * dp[i-j];
            }
        }
        return dp[n];
    }
}

三、416. 分割等和子集

题目链接:https://leetcode.cn/problems/partition-equal-subset-sum/description/
思路:0 1背包问题,划分等和子集,如果和为偶数就可以划分,奇数就不能划分。偶数可以划分,就等于用数组里的数把总和的一半给填满,那么就可以划分等和子集,从而转化为0 1 背包问题。
0 1 背包特点,物品在外,背包在内,背包逆序。内外关系为的是防止,大物品放入后,小物品无法再放入。背包逆序为的是防止物品重复放入。

class Solution {
    public boolean canPartition(int[] nums) {
        int sum = 0;
        for(int i = 0; i < nums.length; i++) {
            sum += nums[i];
        }
        if(sum % 2 == 1) return false;
        sum /= 2;
        int[] dp = new int[sum+1];
        for(int i = 0; i < nums.length; i++) {
            for(int j = sum; j >= nums[i]; j--) {
                dp[j] = Math.max(dp[j], dp[j-nums[i]] + nums[i]);
            }
        }
        return dp[sum] == sum;
    }
}

四、1049. 最后一块石头的重量 II

题目链接:https://leetcode.cn/problems/last-stone-weight-ii/description/
思路:求最后一块是否的重量,就是两两抵消,求最后剩余的无法抵消的数,转换思路想一想其实就是尽量把石头分成两堆大小接近的堆,然后比较最小差值,所以题目就转变成了0 1背包问题,总数和的一半作为背包,求的结果后,乘2与总数相减即得最后一块是否的重量。

class Solution {
    public int lastStoneWeightII(int[] stones) {
        int sum = 0, total = 0;
        for(int i = 0; i < stones.length; i++) {
            total += stones[i];
        }

        sum = total / 2;
        int[] dp = new int[sum+1];
        for(int i = 0; i < stones.length; i++) {
            for(int j = sum; j >= stones[i]; j--) {
                dp[j] = Math.max(dp[j], dp[j - stones[i]] + stones[i]);
            }
        }
        return total - dp[sum] * 2;
    }
}

五、494. 目标和

题目链接:https://leetcode.cn/problems/target-sum/description/
思路:0 1 背包求组合数,想办法转化为背包,得到背包空间,因为分为正数和负数,a + b = sum; a - b = target。
a = (sum+target) / 2;
由此可以得到正数背包,从而转变从背包求组合数,定义dp[j]表示,背包空间为j时的物品组合数,那么自然,递推公式为dp[j] += dp[j - nums[i]]; 所以需要初始化为1.

class Solution {
    public int findTargetSumWays(int[] nums, int target) {
        int sum = 0;
        for(int i = 0; i < nums.length; i++) {
            sum += nums[i];
        }
        if(sum < Math.abs(target) || (sum + target) % 2 == 1) return 0;
        int left = Math.abs((sum + target) / 2);
        int[] dp = new int[left+1];
        dp[0] = 1;
        for(int i = 0; i < nums.length; i++) {
            for(int j = left; j >= nums[i]; j--) {
                dp[j] += dp[j - nums[i]];
            }
        }
        return dp[left];
    }
}

最近更新

  1. TCP协议是安全的吗?

    2024-05-01 00:42:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-05-01 00:42:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-05-01 00:42:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-05-01 00:42:02       20 阅读

热门阅读

  1. 重要数据的识别因素

    2024-05-01 00:42:02       12 阅读
  2. 人工智能入门:你需要掌握哪些基础知识?

    2024-05-01 00:42:02       10 阅读
  3. 【设计模式】14、strategy 策略模式

    2024-05-01 00:42:02       11 阅读
  4. 你用过最好用的AI工具有哪些?【模板】

    2024-05-01 00:42:02       10 阅读
  5. 如何在React中实现状态钩子

    2024-05-01 00:42:02       13 阅读
  6. 剧情游戏如何制作?

    2024-05-01 00:42:02       8 阅读
  7. 跟我学C++中级篇——内联

    2024-05-01 00:42:02       11 阅读
  8. pytest.ini配置文件

    2024-05-01 00:42:02       13 阅读
  9. Three CSS2D 渲染器 月球绕地球旋转

    2024-05-01 00:42:02       12 阅读