提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
题目描述
给你一个整数数组 nums 和一个整数 target 。
向数组中的每个整数前添加 ‘+’ 或 ‘-’ ,然后串联起所有整数,可以构造一个 表达式 :
例如,nums = [2, 1] ,可以在 2 之前添加 ‘+’ ,在 1 之前添加 ‘-’ ,然后串联起来得到表达式 “+2-1” 。
返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。
示例 1:
输入:nums = [1,1,1,1,1], target = 3
输出:5
解释:一共有 5 种方法让最终目标和为 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
+1 + 1 + 1 + 1 - 1 = 3
示例 2:
输入:nums = [1], target = 1
输出:1
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/target-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题过程
解题思路
动态规划:本题有一些技巧,首先以neg表示添加"-“号的所有数的加和
则sum - neg表示添加”+"号的所有数的加和
因此可以得到这样的表达式:target = (sum - neg) - neg, 即得neg = (sum - target) / 2
于是问题转化为求和为neg的不同方案数
动态规划数组dp[i][j]表示前i个数组元素和为j的方案,最终结果便是dp[nums.length][neg]
状态转移方程为:
dp[i][j] += dp[i - 1][j] + dp[i - 1][j - nums[i - 1]],j >= nums[i - 1] (nums[i - 1]可选和不选);
dp[i][j] = dp[i - 1][j], j < nums[i - 1] (nums[i - 1]选不了,因为j比它小);
class Solution {
public int findTargetSumWays(int[] nums, int target) {
int sum = 0;
for(int i = 0; i < nums.length; i++){
sum += nums[i];
}
int neg = (sum - target) / 2;
if(neg < 0 || (sum - target) % 2 != 0){
return 0;
}
int dp [][] = new int[nums.length + 1][neg + 1];
dp[0][0] = 1;
for(int i = 1; i < nums.length + 1; i++){
for(int j = 0; j < neg + 1; j++){
if(j >= nums[i - 1]){
dp[i][j] += dp[i - 1][j] + dp[i - 1][j - nums[i - 1]];
}else{
dp[i][j] = dp[i - 1][j];
}
}
}
return dp[nums.length][neg];
}
}