题目描述

题目链接:494. 目标和

给你一个整数数组 nums 和一个整数 target

向数组中的每个整数前添加 '+''-' ,然后串联起所有整数,可以构造一个 表达式

  • 例如,nums = [2, 1] ,可以在 2 之前添加 '+' ,在 1 之前添加 '-' ,然后串联起来得到表达式 "+2-1"

返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。

示例1:

1
2
3
4
5
6
7
8
输入: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:

1
2
输入:nums = [1], target = 1
输出:1

提示:

  • 1 <= nums.length <= 20
  • 0 <= nums[i] <= 1000
  • 0 <= sum(nums[i]) <= 1000
  • -1000 <= target <= 1000

我的题解

方法一:动态规划

思路

由题意,求出数组的和为sum,那么添加运算符号后,则最终的结果范围为:-sum~sum,

设dp[i][j]为前i个数中和为j的个数,因此每一个状态都有dp[i-1][0~j]推出,以实例一为例:

1
2
3
4
  -5 -4 -3 -2 -1 0 1 2 3 4 5
1 0 0 0 0 1 0 1 0 0 0 0
2 0 0 0 1 0 2 0 1 0 0 0
......

每一行状态都由上一组状态推出,这里使用map进行计算

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public int findTargetSumWays(int[] nums, int target) {
HashMap<Integer, Integer> map = new HashMap<>();
map.put(nums[0], map.getOrDefault(nums[0], 0) + 1);
map.put(-nums[0], map.getOrDefault(-nums[0], 0) + 1);
for (int i = 1; i < nums.length; i++) {
int index = i;
HashMap<Integer, Integer> t = map;
HashMap<Integer, Integer> m = new HashMap<>();
map.forEach((k, v) -> {
m.put(k + nums[index], m.getOrDefault(k + nums[index], 0) + t.get(k));
m.put(k - nums[index], m.getOrDefault(k - nums[index], 0) + t.get(k));
});
map = m;
}
return map.getOrDefault(target, 0);
}
}