[LeetCode] 416 Partition Equal Subset Sum

Posted fengzw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[LeetCode] 416 Partition Equal Subset Sum相关的知识,希望对你有一定的参考价值。

原题地址:

https://leetcode.com/problems/partition-equal-subset-sum/description/

 

题目:

 

题解:

这道题给定一个数组,求这个数组是否可以分成两个数组,使这两个数组各自的元素之和相等。

首先,假如这个数组本身的元素之和是一个奇数时,是不能把这个数组分成两个和相等的数组的。因此,利用这一点我们可以排除掉很多情况,直接得出结果。

而对于数组本身元素之和为偶数的情况,我们才需要算法去解决。我们可以将问题转化为以下的形式:是否有一个子数组的元素之和,恰好等于原数组元素之和的一半呢?而对于原数组中的每一个元素,都有两种状态:在子数组里面或者不在子数组里面(先假设存在这个子数组)。这样一看,我们就能发现这个问题与0-1背包问题非常相似,因此我们可以采用0-1背包问题的解法去解决这道问题。

在这道题目中,原数组里面的每个元素都可以看作是一种物品,而这件物品的重量和价值都为元素值;原数组的和的一半可看作背包的最大承重量,而当背包能放下物品的最大价值为原数组和的一半时,就返回真,否则返回假。

采用二维数组解决的代码如下:

class Solution {
public:
   bool canPartition(vector<int>& nums) {
        int sum = accumulate(nums.begin(), nums.end(), 0);
        if (sum % 2 == 1) return false;
        sum /= 2;
        int ** a = new int*[nums.size()];
        for (int i = 0; i < nums.size(); i++) {
            a[i] = new int[sum + 1];
        }
        for(int i=nums[0];i<=sum;i++){
             a[0][i] = nums[0];
        }
        for (int i = 1; i < nums.size(); i++) {
            for (int j = nums[i]; j <= sum; j++) {
                a[i][j] = a[i - 1][j] > a[i - 1][j - nums[i]] + nums[i] ? a[i - 1][j] : a[i - 1][j - nums[i]] + nums[i];
            }
        }
       return a[nums.size() - 1][sum] == sum;
   }

};

 

上面的代码值得注意的是下面这一句:

for(int i = nums[0]; i <= sum;i++){
    a[0][i] = nums[0];
}

 

由于这道题目中“物品”是从第0件开始算起的,这和平时做的0-1背包问题从第1件物品算起的初始化方法不一样,值得注意。

 

采取一维数组解决的代码:

class Solution {
public:
   bool canPartition(vector<int>& nums) {
        int sum = accumulate(nums.begin(), nums.end(), 0);
        if (sum % 2 == 1) return false;
        sum /= 2;
        int * dp = new int[sum + 1];for (int i = 0; i < sum + 1; i++) {
       dp[i] = 0;
     }for (int i = 0; i < nums.size(); i++) { for (int j = sum; j >= nums[i]; j--) { dp[j] = dp[j] > dp[j - nums[i]] + nums[i] ? dp[j] : dp[j - nums[i]] + nums[i]; } } return dp[sum] == sum; } };

 

用一维数组来解决这个问题,就无需考虑上面从第几件物品算起的问题,只需改一下第一层循环i的起始值即可。

 

这道题给了我一个启发:这类题目,即物品(数组元素)有存在与否两种状态的题目,都可以用0-1背包的思想和解法进行解决。推广一下,可以用背包问题的思想去解决。(假如允许数组元素重复岂不是可以用完全背包的方法解决?)

 

以上是关于[LeetCode] 416 Partition Equal Subset Sum的主要内容,如果未能解决你的问题,请参考以下文章

Leetcode 416. Partition Equal Subset Sum

LeetCode 416. Partition Equal Subset Sum

[动态规划] leetcode 416 Partition Equal Subset Sum

[LeetCode] 416 Partition Equal Subset Sum

leetcode 416. Partition Equal Subset Sum 分割等和子集(中等)

(Java) LeetCode 416. Partition Equal Subset Sum —— 分割等和子集