代码随想录算法训练营第42天 | 416. 分割等和子集

发布于 2023-02-26  235 次阅读


AI 摘要

该篇文章介绍了力扣上题目编号为416的问题:分割等和子集。通过使用动态规划的方法,确定dp数组以及下标的含义,递推公式,dp数组的初始化,遍历顺序等步骤,最终得到可行的AC代码。同时,还提供了标准答案,对比本篇文章的代码进行学习和优化。

416. 分割等和子集 - 力扣(Leetcode)

思路:

  • 使用动态规划

    1. 确定dp数组以及下标的含义

      • dp[j]的定义为:容量为j的背包,所背的物品价值最大可以为dp[j]
    2. 确定递推公式

      • 状态转移方程为dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);
    3. dp数组如何初始化

      vector<int> dp(10001, 0);
    4. 确定遍历顺序

      for(int i = 0; i < nums.size(); ++i) {
          for(int j = sum; j >= nums[i]; --j) {
              dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);
          }
      }

我的AC代码

// 时间复杂度O(n2),空间复杂度O(n)
class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int sum = 0;
        for(int i = 0; i < nums.size(); ++i) {
            sum += nums[i];
        }
        if(sum % 2 == 1) {
            return false;
        }
        else {
            sum /= 2;
        }
        vector<int> dp(10001, 0);
        for(int i = 0; i < nums.size(); ++i) {
            for(int j = sum; j >= nums[i]; --j) {
                dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);
            }
        }
        if(dp[sum] == sum) {
            return true;
        }
        return false;
    }
};

标准答案

// 时间复杂度O(n2),空间复杂度O(n)
class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int sum = 0;

        // dp[i]中的i表示背包内总和
        // 题目中说:每个数组中的元素不会超过 100,数组的大小不会超过 200
        // 总和不会大于20000,背包最大只需要其中一半,所以10001大小就可以了
        vector<int> dp(10001, 0);
        for (int i = 0; i < nums.size(); i++) {
            sum += nums[i];
        }
        // 也可以使用库函数一步求和
        // int sum = accumulate(nums.begin(), nums.end(), 0);
        if (sum % 2 == 1) return false;
        int target = sum / 2;

        // 开始 01背包
        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]);
            }
        }
        // 集合中的元素正好可以凑成总和target
        if (dp[target] == target) return true;
        return false;
    }
};