• LeetCode算法题解(动态规划,背包问题)|LeetCode416. 分割等和子集


    LeetCode416. 分割等和子集

    题目链接:416. 分割等和子集
    题目描述:

    给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

    示例 1:

    输入:nums = [1,5,11,5]
    输出:true
    解释:数组可以分割成 [1, 5, 5] 和 [11] 。

    示例 2:

    输入:nums = [1,2,3,5]
    输出:false
    解释:数组不能分割成两个元素和相等的子集。
    

    提示:

    • 1 <= nums.length <= 200
    • 1 <= nums[i] <= 100
    算法分析:
    定义dp数组及下标含义:

    dp[i][j]表示0~i中每个元素任取,其总和不大于j的最大值(能够在容量为j的背包里装下的最大值)。

    递推公式:

    dp[i][j] = max(dp[i-1][j], dp[i-1][j-nums[i]]+nums[i])。

    初始化:

    子集的总和不会超过原数组总和的一半,所以dp代表值的那个维度长度取其一半即可。

    1. vectorint>>dp(nums.size(), vector<int>(sum + 1, 0));
    2. for(int i = nums[0]; i <= sum; i++) {
    3. dp[0][i] = nums[0];
    4. }
    遍历顺序:

    元素遍历的for循环在外层,总和值的遍历在内层。

    代码如下:

    1. class Solution {
    2. public:
    3. bool canPartition(vector<int>& nums) {
    4. int sum = 0;
    5. for(int i = 0; i < nums.size(); i++) {
    6. sum += nums[i];
    7. }
    8. if(sum % 2 != 0) return false;
    9. sum /= 2;
    10. vectorint>>dp(nums.size(), vector<int>(sum + 1, 0));
    11. for(int i = nums[0]; i <= sum; i++) {
    12. dp[0][i] = nums[0];
    13. }
    14. for(int i = 1; i < nums.size(); i++) {
    15. for(int j = 0; j <= sum; j++) {
    16. if(j < nums[i]) dp[i][j] = dp[i - 1][j];
    17. else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - nums[i]] + nums[i]);
    18. if(dp[i][j] == sum) return sum;
    19. }
    20. }
    21. return false;
    22. }
    23. };

    状态压缩,将二维数组转化成一维数组(内从循环遍历总和值要倒着遍历):

    1. class Solution{
    2. public boolean canPartition(int[] nums) {
    3. int sum = 0;
    4. for(int i = 0; i < nums.length; i++)
    5. sum += nums[i];
    6. if(sum % 2 != 0) return false;
    7. sum /= 2;
    8. int[] dp = new int[sum + 1];
    9. for(int i = nums[0]; i <= sum; i++)
    10. dp[i] = nums[0];
    11. for(int i = 1; i < nums.length; i++) {
    12. for(int j = sum; j >= nums[i]; j--) {
    13. dp[j] = Math.max(dp[j], dp[j - nums[i]] + nums[i]);
    14. }
    15. if(dp[sum] == sum) return true;
    16. }
    17. return false;
    18. }
    19. }

    总结

    对于类似背包的问题,可以将其视为背包问题看待,找准背包容量和物品的对应对象。

  • 相关阅读:
    docker在java项目中打成tar包
    计算机网络规划与设计
    【SemiDrive源码分析】【MailBox核间通信】43 - 基于Mailbox IPCC RPC 实现核间通信(代码实现篇)
    JavaScript字符串③
    Mybatis 框架 ( 四 ) QueryWrapper
    学习笔记5--高精地图解决方案
    Linux常用命令——find命令大全
    聊聊 C++ 和 C# 中的 lambda 玩法
    简易图像处理器的设计
    SSM+图书馆电子文件资源管理 毕业设计-附源码091426
  • 原文地址:https://blog.csdn.net/2201_76107580/article/details/134564137