Leetcode one question of the day: 416.partition-equal-subset-sum (partition equal and subset)

Insert picture description here
Idea : This question is very similar from the perspective of dynamic programming0-1 knapsack problem, The latter needs to maximize the value under the condition of less than or equal to the backpack capacity, here it is exactly equal to half of the sum of the array;
1°, in order to meet the condition, the sum of the array summust be an even number, and the target value target=sum/2, all you have to do is Find several elements in the array and make the sum be target;
2°, establish a dynamic programming model bool dp[len][taeget+1]中,dp[i][j]的值表示数组[0,i]中是否存在若干个元素的和为j,;
3°, boundary condition {对于所有dp[i][0]=true,因为数组[0,i]我都可以不选从而达到j=0的条件} {dp[0][nums[0]]=true,选择数组第一个元素(nums[0])能让j=nums[0]满足}
4°, dp[i][j]there are two cases for the value of:

  • If j<nums[i], then it nums[i]must not be selected, it is more than j =>dp[i][j]=dp[i-1][j]
  • If j>=nums[i], then you nums[i]can choose not to choose => df[i][j]=dp[i-1][j](不选)||dp[i-1][j-nums[i]](选)
    5°, return dp[len-1][target]you can finally

The detailed version can be found in the solution=> Leikou official solution
Insert picture description here

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];
    }
};

Guess you like

Origin blog.csdn.net/wyll19980812/article/details/109010800