da42:背包问题|● 416. 分割等和子集

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

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

1.代码

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int sum = 0;
        for (int i: nums) {
            sum += i;
        }
        if (sum % 2 != 0) return false;
        sum /= 2;
         vector<int>f(sum + 1);
         for (int i = 0; i < nums.size(); i++) {
             for (int j = sum; j >= nums[i]; j--) {
                 f[j] = max(f[j], f[j - nums[i]] + nums[i]);
             }
         }
         if (f[sum] == sum) return true;
         else return false;
    }
};

2.思路

题目的意思是看下可以把这个数组分成两个部分这两部分相加会相等吗如果相等返回false否则返回true,所以只要有一部分数组相加等于nums数组的总和的一半就行了

由此就能把问题转化成从n个数据中找到数据相加等于sum/2的组合可以用回溯法

3.回溯法超时

class Solution {
public:
  int res;
  int flag = 0;
    void backtracking(int sum, vector<int>& nums, int startindex) {
        if (res > sum || flag == 1) return;
        if (res == sum) flag = 1;
        for (int i = startindex; i < nums.size(); i++) {
            res += nums[i];
            backtracking(sum, nums, i + 1);
            res -= nums[i];
        }
   }
    bool canPartition(vector<int>& nums) {
        int sum = 0;
        for (int i: nums) {
            sum += i;
        }     
        if (sum % 2 != 0) return false;  
        sum = sum / 2;
        backtracking(sum, nums, 0);
        if (flag == 1) return true;
        else return false;
    }
};

4.动规五部曲

还可以转化为求背包大小为sum/2的可以装入的最大价值最后只要判断最后一个背包的价值等于不等于sum/2就知道结果了所以可以使用01背包

1.确定dp数组和其下标的含义

dp[j]代表大小为j的背包可以装入的最大价值这里的背包空间和价值都是sum

2.确定递推数组

01背包在每一个问题中可以转化为选还是不选当前的物品这里就是选不选这个值由此可以得出

不选f[i][j] = f[i - 1][j], 选f[i -1] [j - nums[i]] + nums[i], 可以转化成一维数组把i去掉就行了

选择第i个物品代表一定要选他代表需要留足够的空间来选他,所以需要减去所需要占的空间

 3.初始化

初始化就是当小于该体积时就为0不用变化我们在先后顺序那里再判断

4.遍历顺序

先遍历物品不断加每一个物品 第二层循环是递推每一个不同大小的背包

这里是反的顺序遍历因为反的遍历可以避免重复加上该物品数据逆序就能避免了自己可以进行推导

背包大小小于物品的大小时就转不下就不需要遍历了可以在for循环中判断

5.递推模拟dp数组

模拟

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6