416. Partition Equal Subset Sum

本文探讨了如何通过动态规划解决背包问题的一个实例——Partition Equal Subset Sum问题,即判断一个正整数数组是否能被分为两个子集,使每个子集的元素之和相等。文章详细介绍了动态规划的应用方法及步骤。

原题如下:

Partition Equal Subset Sum

Given a non-empty arraycontaining only positive integers, find if the array can be partitionedinto two subsets such that the sum of elements in both subsets is equal.

Note:

1.   Each of the array element will not exceed 100.

2.   The array size will not exceed 200.

Example 1:

Input: [1, 5, 11,5]

 

Output: true

 

Explanation: Thearray can be partitioned as [1, 5, 5] and [11].

Example 2:

Input: [1, 2, 3, 5]

 

Output: false

 

Explanation: Thearray cannot be partitioned into equal sum subsets.

题目大意:这道题目意思大概是给定一个正整数的数组,看是否这个正整数的数组能够两部分,每部分的和相等。

解题思路:这道题目如果用暴力的方法挺复杂的,将数组中所有不同情况的数字组合起来,这样的复杂度达到了指数的级别,显然不是一种很好的方法;这里我们采用动态规划的思想,将这个问题抽象成一个背包问题,也就是说给定n个数,第i个数价值为nums[i],现在就是判断是否存在能让背包里装价值为sum/2的情况,我们定义一个大小为sum/2(sum为数组中所有元素的和)的数组,然后根据状态转移方程f[v]=max{f[v],f[v-c[i]]+w[i]}计算出f[sum/2],然后判断f[sum/2]是否等于sum/2,是的话,返回true,否则,返回false;

算法:

1、       求出数组的和sum,而且判断sum是否为偶数,不为偶数的话显然不能对半分,这个时候返回false即可,

2、       若sum的值为偶数,则定义一个大小为sum/2+1的数组f,并初始化为0;

3、       然后用一个二重循环,外层循环是i-n(n为数组大小),内层循环则是从sum/2到0,这里顺序不能颠倒,这样使用内层循环可以节省空间,然后根据状态转移方程f[v]=max{f[v],f[v-c[i]]+w[i]}计算出结果。

4、       循环结束后,判断f[sum/2]是否等于sum/2,是的话返回true,否则返回false。

算法复杂度分析:整个函数只用了两层循环解决问题,所以最坏复杂度为O(NV),其中N是数组大小,V是数组总和的一半。

具体代码如下:

class Solution {

public:

    bool canPartition(vector<int>&nums) {

        int n=nums.size();

        if(n==0)return true;

        if(n==1)return false;

        int sum=0;

        for(int i=0;i<n;i++){

             sum+=nums[i];

        }

        if(sum%2==1)

        return false;

        vector<int> t(sum/2+1,0);

        //vector<vector<int> >t(n+1,temp);

        for(int i=1;i<=n;i++){

             for(intj=sum/2;j>=0;j--){

                 if(j>=nums[i-1])

                    t[j]=max(t[j],t[j-nums[i-1]]+nums[i-1]);

             }

        }

        return t[sum/2]==sum/2;

    }

};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值