Leetcode每日一题:416.partition-equal-subset-sum(分割等和子集)

在这里插入图片描述
思路:这题从动态规划的思想上来看很像0-1背包问题,后者需要小于等于背包容量的条件下价值最大化,这里则是刚好等于数组之和的一半;
1°,要想满足条件,数组之和sum必须为偶数,并且目标值target=sum/2,所要做的就是在数组中找到若干个元素,使之和为target
2°,建立动态规划模型,bool dp[len][taeget+1]中,dp[i][j]的值表示数组[0,i]中是否存在若干个元素的和为j
3°,边界条件{对于所有dp[i][0]=true,因为数组[0,i]我都可以不选从而达到j=0的条件} {dp[0][nums[0]]=true,选择数组第一个元素(nums[0])能让j=nums[0]满足}
4°,对于dp[i][j]的取值有以下两种情况:

  • 如果j<nums[i],那么nums[i]必不能选,选了就超过j了 => dp[i][j]=dp[i-1][j]
  • 如果j>=nums[i],那么nums[i]可选可不选 => df[i][j]=dp[i-1][j](不选)||dp[i-1][j-nums[i]](选)
    5°,最后return dp[len-1][target]即可

详细版可看题解=>力扣官方题解
在这里插入图片描述

class Solution {
    
    
public:
    bool canPartition(vector<int> &nums)
    {
    
    
        int len = nums.size();
        if (len < 2)
            return false;
        if (len == 2 && nums[0] != nums[1])
		    return false;
        int sum = 0, target = 0;
        for (int i = 0; i < len; i++)
        {
    
    
            sum += nums[i];
        }
        if (sum & 1) //如果sum是奇数,直接return false
        {
    
    
            return false;
        }
        else //如果是偶数,说明可能为true 可能为false,如果能凑出若干整数使它们和为sum/2,说明为true
        {
    
    
            target = sum / 2;
        }
        //dp[i][j]标识从数组[0,i]下标范围内选区若干整数(可以是0个),是否存在一种方案使得被选取得正整数和等于j
        bool **dp = new bool *[len];
        for (int i = 0; i < len; i++)
        {
    
    
            dp[i] = new bool[target + 1];
            for (int j = 0; j < target + 1; j++)
            {
    
    
                dp[i][j] = false;
            }
        }

        //边界条件1:对于所有j=0,dp[i][0]=true,因为我可以选0个达到j=0;
        for (int i = 0; i < len; i++)
        {
    
    
            dp[i][0] = true;
        }
        //边界条件2:当i=0时,只有1个整数(nums[0])能被选到,所以dp[0][nums[0]]=true
        dp[0][nums[0]] = true;

        for (int i = 1; i < len; i++)
        {
    
    
            for (int j = 1; j < target + 1; j++)
            {
    
    
                //如果j>=nums[i],则nums[i]可选可不选
                if (j >= nums[i])
                {
    
    
                    //            选nums[i]              不选nums[i]
                    dp[i][j] = dp[i - 1][j - nums[i]] || dp[i - 1][j];
                }
                //如果j<nums[i],则说明nums[i]必不能选
                else
                {
    
    
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }
        return dp[len - 1][target];
    }
};

猜你喜欢

转载自blog.csdn.net/wyll19980812/article/details/109010800