1,问题描述
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
2,初步思考
最为核心的事情是:要分析出题目里面具体的模式,这个题目最终转变为背包问题!
求解背包大小为sum/2能够最大装多少石头!!!
同时也要求我们会背包问题的求解
3,代码处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| import java.util.Arrays;
public class _494目标和 {
public int findTargetSumWays_1d(int[] nums, int target) { int n = nums.length; int sum = Arrays.stream(nums).sum(); target = sum - target; if (target % 2 == 1 || target < 0) return 0; target >>= 1; int[] dp = new int[target + 1]; dp[0] = 1; for (int i = 1; i <= n; i++) { dp[0] = target % nums[i - 1] == 0 ? 1 : 0; for (int j = target; j >= nums[i - 1]; j--) { dp[j] = dp[j] + dp[j - nums[i - 1]]; } } return dp[target]; }
public int findTargetSumWays(int[] nums, int target) { int n = nums.length; int sum = Arrays.stream(nums).sum(); target = sum - target; if (target % 2 == 1 || target < 0) return 0; target >>= 1; int[][] dp = new int[n + 1][target + 1]; dp[0][0] = 1; for (int i = 1; i <= n; i++) { int num = nums[i - 1]; for (int j = 0; j <= target; j++) { dp[i][j] = dp[i - 1][j]; if (j >= num) { dp[i][j] += dp[i - 1][j - num]; } } } return dp[n][target]; }
public static void main(String[] args) { _494目标和 targetSum = new _494目标和();
System.out.println(targetSum.findTargetSumWays_1d(new int[]{1, 2, 1}, 0)); } }
|
4,拓展知识点
背包问题类型:
01背包:每件物品只有一个
完全背包:每种物品有无限个
多重背包:每种物品有限定的个数,二进制优化
背包方案:有多少种背包方案可行
其他变形:例如多种容量问题