416. Partition Equal Subset Sum 题解

416. Partition Equal Subset Sum

 
  My Submissions
  • Total Accepted: 5652
  • Total Submissions: 15309
  • Difficulty: Medium
  • Contributors: Admin

Given a non-empty array containing only positive integers, find if the array can be partitioned into 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: The array can be partitioned as [1, 5, 5] and [11].

Example 2:

Input: [1, 2, 3, 5]

Output: false

Explanation: The array cannot be partitioned into equal sum subsets.


解题思路:

本题问是否可以将一个集合分为两个子集使得两个子集和相等。这个问题可以等价为可否在一个集合中找到一个子集A,使得该子集A中所有元素的和为整个集合元素的和的一半。

对于集合的每个元素,或者属于子集A,或者不属于。由此可得到,即穷举所有元素的所有情况,看是否符合条件。

help(nums,half-nums[i],i-1)||help(nums,half,i-1)

但是直接这样显然会引起大量的重复运算导致超时。所以此处设立一个大小为half+1的res向量来保存中间的计算结果,初始化向量中所有项为-1。令i<=half,如果i可以表示为集合中的某些元素之和,则res[i]=1,否则res[i]=0,如果res[i]=-1,则说明i不知道是否能表示成集合中某些元素和,此时需要计算。

代码展示:

class Solution {
public:
    vector<int> res;
    bool help(vector<int> &nums,long long half,int i)
    {
        if(half<0) return false; // 一定要注意half小于0的情况,由于所有的元素均为正值,half小于0时必为false
        if(res[half]!=-1) return res[half];
        if(half==0) 
        {
            res[0]=1;;
            return true;
        }
        if(i<0)
        {
            res[half]=0;
            return false;
        }
        res[half]=help(nums,half-nums[i],i-1)||help(nums,half,i-1);
        if(res[half]==0) return false;
        return true;
        
    }
    bool canPartition(vector<int>& nums) {
        int n = nums.size();
        if(!n) return true;
        if(n==1&&(nums[0]!=0)) return false;
        if(n==1&&(nums[0]==0)) return true;
        long long sum=0;
        for(int i=0;i<n;i++)
        {
            sum+=nums[i];
        }
        if(sum%2!=0) return false;
        long long half = sum/2;
        for(int i=0;i<=half;i++)
        {
            res.push_back(-1);
        }
        long long tmp_sum=0;
        return help(nums,half,n-1);
        
        
    }
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值