题目地址: https://leetcode-cn.com/problems/target-sum/
题目描述:
给定一个非负整数数组,a1, a2, ..., an, 和一个目标数,S。现在你有两个符号 + 和 -。对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前面。
返回可以使最终数组和为目标数 S 的所有添加符号的方法数。
示例:
输入:nums: [1, 1, 1, 1, 1], S: 3输出:5
解释:
-1+1+1+1+1 = 3
+1-1+1+1+1 = 3
+1+1-1+1+1 = 3
+1+1+1-1+1 = 3
+1+1+1+1-1 = 3
一共有5种方法让最终目标和为3。
提示:
数组非空,且长度不会超过 20 。
初始的数组的和不会超过 1000 。
保证返回的最终结果能被 32 位整数存下。
参考代码:
// 二维数组
class Solution{
public:
int findTargetSumWays(vector<int>& nums, int target) {
int sum = 0;
for (int i = 0; i<nums.size(); i++) {
sum = sum + nums[i];
}
// a + b = s a-b = target , a = (s + target) / 2
//转化为: 从 nums 几个数 使 其相加等于 a
int a = sum + target;
if ( a < 0) { // 边界情况处理
return 0;
}
if (a %2 != 0) {
return 0;
}
a = a /2;
// 第一种 dp[i][j] (前i个数,和为j) = dp[i-1][j] + d[i-1][j-num[i]]
vector<vector<int>> dp = vector<vector<int>>(nums.size()+1,vector<int>(a+1,0));
// 第一行初始化 选中时候,使 其为1
if (nums[0] <=a) {
dp[0][nums[0]] = 1;
}
if (nums[0] ==0 ){ //边界情况处理
dp[0][nums[0]] = 2;
} else{
dp[0][0] = 1;
}
for (int i = 1; i< nums.size(); i++) {
for (int j = 0; j<=a; j++) { // j<=a
if (j >= nums[i]) {
dp[i][j] = dp[i-1][j] + dp[i-1][j-nums[i]];
} else {
dp[i][j] = dp[i-1][j];
}
}
}
return dp[nums.size()-1][a];
}
};
//一维数组
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int S) {
int sum = 0;
for (int i = 0; i<nums.size(); i++) {
sum = sum + nums[i];
}
int bagsise = sum + S;
if (bagsise < 0) {
return 0;
}
if (bagsise % 2 == 1) {
return 0;
}
bagsise = bagsise / 2;
vector<int> dp = vector<int>(bagsise+1,0);
// dp[i] = dp[i] +dp[i-num[i]] 和的大小为i的 数量
dp[0] = 1;
for (int i = 0; i< nums.size(); i++) {
for (int j = bagsise; j >= nums[i]; j--) {
dp[j] = dp[j] + dp[j-nums[i]];
}
}
return dp[bagsise];
}
};
网友评论