动态规划——在数组中找到目标求和方式

Posted

技术标签:

【中文标题】动态规划——在数组中找到目标求和方式【英文标题】:dynamic programming--find target sum ways in an array 【发布时间】:2017-06-15 11:48:42 【问题描述】:

在leetcode中遇到一个问题,看了别人用DP的解决方案,但有一点看不懂,希望大家指点一下。

问题是:给定一个只包含正整数的非空数组,找出有多少种方法可以选择其中一些和等于目标 S 的整数。

解决办法是:

int findTargetSumWays(vector<int>& nums, int S) 

    int n = nums.size();
    vector<int> dp(S+1, 0);

    dp[0] = 1;
    for(int i=0; i<n; i++)
        for(int j=S; j>=nums[i]; j--)
        //for(int j=nums[i]; j<=S; j++) //why it is wrong?
        

            dp[j] += dp[j-nums[i]];
        
    return dp[S];  

代码中,第二个循环从S向下计数到nums[i],但是为什么不能从nums[i]向上计数到S呢?我知道如果向上计数,结果会比答案大得多,但我无法弄清楚向上计数的本质问题。

感谢任何帮助!

【问题讨论】:

【参考方案1】:

由于nums[i] 保证为正数,因此:

dp[j] += dp[j-nums[i]]

根据同一数组中 smaller 索引处的元素值修改数组中 larger 索引处的元素。

因为j 从高位开始并递减,所以在每次迭代中,保证您需要读取的值(小于 j 的索引)不是您已经覆盖的值(大于 j 的索引)。

相反,如果您从 j 低开始并递增它,那么您最终会覆盖稍后将在循环中读取的值。然后它们将具有不正确的值并产生错误的答案。

这类事情是在原地操作数组的算法中非常常见的考虑因素。

【讨论】:

【参考方案2】:

当第二个循环向下计数时,您计算对数组元素求和的所有可能性并获得目标S,其中数组的每个元素只能被取一次。但是,当第二个循环向上计数时,您会计算数组的每个元素都可以被取任意次数的可能性。 所以第二个数字大于或等于第一个数字。

【讨论】:

以上是关于动态规划——在数组中找到目标求和方式的主要内容,如果未能解决你的问题,请参考以下文章

动态规划算法介绍

破解大厂算法面试最难题型:动态规划之表达式规划

动态规划第七篇:01背包问题(目标和 + 一和零)

动态规划第七篇:01背包问题(目标和 + 一和零)

494. 目标和 回溯法+动态规划

奶牛零食 - 自下而上的动态规划