(一)、题目描述
(二)、思路
我先来解释一下这道题,就是给定一个数组,从这个数组中挑选一部分数出来相加,减去剩下的数的和能达到题目所给的「target」。
所以我们设数组的总数和为「sum」,挑选出来的数字和为「left」,剩下的数字和为「right」。由题得:left - right =target。right = sum - left。所以 left - (sum - left) =target。 left = (sum + target) / 2。
将这道题转化为【背包问题】应该是:
我们背包容量为 left,每个数组元素的「价值」与「重量」都是其数值大小,求我们能否装满背包。
(三)、解答方法
我们要求组成 left 的组合,所以每个数只能使用一次,我们应该直接想到【0-1背包】。那么我们可以直接套用【0-1背包】问题的方法。
如果还不了解【0-1背包】问题的小伙伴可以点击这【0-1背包】和【完全背包】详解学习一下【0-1背包】问题。
1.确定dp数组及下标的含义:
【0-1背包】中,dp[j] 表示: 容量为j的背包,所背的物品价值最大可以为dp[j]。 本题中每一个元素的数值既是重量,也是价值。套到本题,dp[j] 表示:凑成背包容量为 j 总共有多少种方法
2.确定递推公式
【01背包】的递推公式为:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
本题,相当于背包里放入数值,那么物品i的重量是nums[i],其价值也是nums[i]。
所以递推公式:dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);
3.初始化dp数组:
从dp[j]的定义来看,首先dp[0]一定是0,其次其他位置也要初始化为0。
这样才能让dp数组在递推的过程中取得最大的价值,而不是被初始值覆盖了。
(四)、代码
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int target) {
int sum=0;
for(int i=0;i<nums.size();i++)
{
sum+=nums[i];
}
if(abs(target)>sum) return 0;
if((target+sum)%2==1)
return 0;
int left=(target+sum)/2;
vector<int> dp(left+1,0);
dp[0]=1;
for(int i=0;i<nums.size();i++)
{
for(int j=left; j >= nums[i]; j--)
{
dp[j]+=dp[j-nums[i]];
}
}
return dp[left];
}
};
总结
这就是本期博客的全部内容了,如果还想了解更多有关【0-1背包】类型的问题请看我的【动态规划之0-1背包】专栏。
谢谢观看,如果觉得博主还不错的话请点个赞和关注再走吧。