Leetcode una pregunta del día: 416.partition-equal-subset-sum (partición igual y subconjunto)

Inserte la descripción de la imagen aquí
Idea : esta pregunta es muy similar desde la perspectiva de la programación dinámica0-1 problema de mochila, Este último necesita maximizar el valor bajo la condición de menor o igual a la capacidad de la mochila, aquí es exactamente igual a la mitad de la suma de la matriz;
1 °, para cumplir con la condición, la suma de la matriz sumdebe ser un número par, y el valor objetivo target=sum/2, todo lo que tiene que hacer es Encuentre varios elementos en la matriz y haga que la suma sea target;
2 °, establezca un modelo de programación dinámica bool dp[len][taeget+1]中,dp[i][j]的值表示数组[0,i]中是否存在若干个元素的和为j,;
3 °, condición de frontera {对于所有dp[i][0]=true,因为数组[0,i]我都可以不选从而达到j=0的条件} {dp[0][nums[0]]=true,选择数组第一个元素(nums[0])能让j=nums[0]满足}
4 °, dp[i][j]hay dos casos para el valor de:

  • Si j<nums[i], entonces no nums[i]debe seleccionarse, es más de j =>dp[i][j]=dp[i-1][j]
  • Si j>=nums[i], entonces nums[i]puede elegir no elegir => df[i][j]=dp[i-1][j](不选)||dp[i-1][j-nums[i]](选)
    5 °, finalmente return dp[len-1][target]puede

La versión detallada se puede encontrar en la solución => Solución oficial de Leikou
Inserte la descripción de la imagen aquí

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

Supongo que te gusta

Origin blog.csdn.net/wyll19980812/article/details/109010800
Recomendado
Clasificación