分割等和子集

题目

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

示例 1:

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

输入:nums = [1,2,3,5]
输出:false

代码以及解释

这里二维数组和一维数组都使用了

#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;

#define yi
//使用二维数组的方法
#ifdef er
class Solution {
public:
    bool canPartition(vector<int>& nums) {
        //背包问题,要是每一个物体只能放一次,那就是01背包,要是可以重复放入的话那就是完全背包
        /*分割成两个相等的子集,那么一个子集的和就是sum/2,那么我去装一个背包大小为sum/2的背包
          背包装满得到的价值是dp[sum/2],那么说明就可以分成两个背包装,每一个装sum/2。
        */
        //如果采用二维数组的方法,那么按照二维的写法有

        int sum = 0;
        for(int i = 0; i < nums.size(); i++) {
            sum += nums[i];
        }
        int target = sum/2;

        if(sum % 2 == 1) {
            return false;
        }
        //sum最大值是20000,那么target就是10000
        vector<vector<int>> dp(nums.size(), vector<int>(10001, 0));
        //dp的第一列不用初始化了,因为已经等于0了,只要初始化dp的第一行就可以了
        for(int i = nums[0]; i <= target; i++) {
            dp[0][i] = nums[0];
        }
        //开始遍历,先遍历物体,再遍历书包
        for(int i = 1; i < nums.size(); i++) {
            for(int j = 0; j <= target; j++) {
                if(j < nums[i]) {
                    dp[i][j] = dp[i - 1][j];
                } else {
                    dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - nums[i]] + nums[i]);
                }
            }
        }
        return dp[nums.size() - 1][target] == target ? true : false;
    }
};
# endif

#ifdef yi

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        //使用一维数组方法,是从二维数组中进化而来

        //定义dp数组(包含了初始化操作dp[0] = 0])
        int sum = 0;
        for(int i = 0; i < nums.size(); i++) {
            sum += nums[i];
        }
        int target = sum/2;

        if(sum % 2 == 1) {
            return false;
        }
        vector<int> dp(10001, 0);
        /*遍历顺序,内层循环是倒序的,但是注意一点,我们是在原来的数组基础之上去改变的,所以
          和二维数组一样的判断if(j < weight[i])就可以直接省去
        */
        for(int i = 0; i < nums.size(); i++) {
            for(int j = target; j >= nums[i]; j--) {
                dp[j] = max(dp[j], dp[j-nums[i]] + nums[i]);
            } 
        }

        for(int i = 0; i <= target; i++) {
            cout << dp[i] << " ";
        }
        cout << endl;
        return dp[target] == target ? true : false;
    }
};

#endif
int main(int argc, char const *argv[])
{   
    system("chcp 65001");
    Solution so;
    vector<int> nums = {1, 5, 11, 5};
    if(so.canPartition(nums) == 1) {
        cout << "真的" << endl;
    }else {
        cout << "假的" << endl;
    }

    return 0;
}

posted @ 2023-07-01 16:53  铜锣湾陈昊男  阅读(13)  评论(0)    收藏  举报