题目:
给你一个整数数组 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
题解:
方法一:
枚举
import java.util.*;
class Solution {
int count = 0;
public int findTargetSumWays(int[] nums, int target) {
calculate(nums, 0, 0, target);
return count;
}
public void calculate(int[] nums, int i, int sum, int target) {
if (i == nums.length) {
if (sum == target) {
count++;
}
} else {
calculate(nums, i + 1, sum + nums[i], target);
calculate(nums, i + 1, sum - nums[i], target);
}
}
}
/**
* @author wyl
*/
public class Main {
public static void main(String[] args) {
Solution s = new Solution();
int[] nums = {1,1,1,1,1};
int target = 3;
int res = s.findTargetSumWays(nums, target);
System.out.println(res);
}
}
方法二:
动态规划——01背包问题
关于背包问题的模板参考这个链接:https://leetcode-cn.com/problems/target-sum/solution/yi-pian-wen-zhang-chi-tou-bei-bao-wen-ti-wa5r/
背包分类的模板:
1、0/1背包:外循环nums,内循环target,target倒序且target>=nums[i];
2、完全背包:外循环nums,内循环target,target正序且target>=nums[i];
3、组合背包:外循环target,内循环nums,target正序且target>=nums[i];
问题分类的模板:
1、最值问题:dp[i] = max/min(dp[i], dp[i-nums]+nums)或dp[i] = max/min(dp[i], dp[i-num]+1);
2、组合问题:dp[i]=dp[i]+dp[i-num];
3、存在问题(bool):dp[i]=dp[i]||dp[i-num];
我们想要的 S = 正数和 - 负数和 = x - y
而已知 x 与 y 的和是数组总和:x + y = sum,得到y = sum - x
列方程求解得到:
可以求出 x = (S + sum) / 2 = target
也就是我们要从 nums 数组里选出几个数,令其和为 target(target 间接给出)。
于是转化为是否可以用 nums 中的数组合和成 target,01 背包问题,外层循环为选择池 nums,内层循环为 target。
dp[i] 表示和为 i 的 num 组合有 dp[i] 种。
外层遍历 nums 每个 num;
内层遍历 target(由大到小)。
对于元素之和等于 i - num 的每一种排列,在最后添加 num 之后即可得到一个元素之和等于 i 的排列,因此在计算 dp[i] 时,应该计算所有的 dp[i − num] 之和。
dp[i] = dp[i] + dp[i - num]
对于边界条件,我们定义 dp[0] = 1 表示只有当不选取任何元素时,元素之和才为 0,因此只有 1 种方案。
最后返回 dp[target]
class Solution {
public int findTargetSumWays(int[] nums, int S) {
int sum = 0;
for (int num : nums) {
sum += num;
}
if (S > sum || (S + sum) % 2 == 1) {
return 0;
}
int target = (S + sum) / 2;
int[] dp = new int[target + 1];
dp[0] = 1;
for (int i = 0; i < nums.length; i++) {
for (int j = target; j >= nums[i]; j--) {
dp[j] = dp[j] + dp[j - nums[i]];
}
}
return dp[target];
}
}
/**
* @author wyl
*/
public class Main {
public static void main(String[] args) {
Solution s = new Solution();
int[] nums = {1, 1, 1, 1, 1};
int target = 3;
int res = s.findTargetSumWays(nums, target);
System.out.println(res);
}
}