416. Partition Equal Subset Sum(数组中有无相等子数组和)

题目:
给定一个仅包含正整数的非空数组,请确定该数组是否可以划分为两个子集,以使两个子集中的元素之和相等。
注意:

每个数组元素将不超过100。
阵列大小不会超过200

思路:
   将数组分为两个子数组,一组得和为P集合,另一组为M集合。求sum P= sum M 是否成立。
   化简后可以利用sum(nums)来计算出其中一个P。再利用dp动态规划来从P开始记录(dp[0]==1)方便设置为1.当P-其他的和 ==0了。
注意其中得dp数组可能会溢出问题。
code:

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int sum=accumulate(nums.begin(),nums.end(),0);
        if(sum%2)
            return false;
        
        int target=sum/2;
        vector<double > dp(target+1);			//之前是int
        dp[0]=1;
        for(int n:nums)
        {
            if(n>target)
                return false;   //说明不可能有哪个子数组。最大只能为target
            for(int i=target; i>=n; i--)
            {dp[i]+=dp[i-n];
             if(dp[target])
                 return true;
            }
        }
        return dp[target];
        
    }
};

为什么溢出呢?
在leetcode中会溢出错误.改成double(8字节得)就好了.
但是在vscode中运行是没有问题得.

对于样本数组[8,5,14,21,6,9,7],如果我们按照从小到大的顺序对它进行排序,可以使用PARTITION算法将其分成两部分。具体操作如下: 1. 选择一个基准数pivot,可以选择数组中的任意一个数。 2. 设置两个指针left和right,分别指向数组的左边和右边。 3. 从左往右扫描数组,当发现比pivot小的数时,将其与left指针所指向的数交换,并将left指针往后移动一位。 4. 从右往左扫描数组,当发现比pivot大的数时,将其与right指针所指向的数交换,并将right指针往前移动一位。 5. 重复执行步骤3和步骤4,直到left指针和right指针相遇。 6. 将基准数pivot与left指针所指向的数交换。 7. 此时,基准数左边的数都比其小,右边的数都比其大。 运用以上步骤,对于样本数组[8,5,14,21,6,9,7]的PARTITION操作可能的结果如下: 1. 选择基准数为8,left指针指向第二个数5,right指针指向最后一个数7。从左往右扫描,发现第一个比8小的数为5,与left指针所指向的数8交换,并将left指针往后移动一位;继续扫描,直到left指针指向值为9的数;从右往左扫描,发现第一个比8大的数为7,与right指针所指向的数8交换,并将right指针往前移动一位;继续扫描,直到left指针与right指针相遇,结束循环。 2. 将基准数8与left指针所指向的数9交换,结果得到分组后的两个数组[5,6,7,8]和[14,21,9]。 注意,由于样本数组是随机的,未必按照以上结果分组。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值