动态规划——在数组中找到目标求和方式
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
,其中数组的每个元素只能被取一次。但是,当第二个循环向上计数时,您会计算数组的每个元素都可以被取任意次数的可能性。
所以第二个数字大于或等于第一个数字。
【讨论】:
以上是关于动态规划——在数组中找到目标求和方式的主要内容,如果未能解决你的问题,请参考以下文章