LeetCode—494. 目标和[Target Sum]——分析及代码[Java]
一、题目
给定一个非负整数数组,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 位整数存下。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/target-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、分析及代码
1. 动态规划
(1)思路
设 dp[i][j] 表示数组中前 i 个元素组成和为 j 的方案数,则对第 i+1 个元素
dp[i + 1][j - nums[i + 1]] += dp[i][j]
dp[i + 1][j + nums[i + 1]] += dp[i][j]
最终,dp[n][S] 就是所求解。
由于初始的数组的和不会超过 1000 ,即数组正负和范围在 [-1000,1000] 范围内,可将下标 j 整体加 1000,用 [0,2000] 表示 [-1000,1000] 的元素和情况。
(2)代码
class Solution {
public int findTargetSumWays(int[] nums, int S) {
if (nums.length == 0 || S > 1000 || S < -1000) // S 可能超出 [-1000,1000]
return 0;
int [][] dp = new int[nums.length + 1][2001];//[-1000,1000] 共有 2001 个数
dp[0][1000] += 1;
for (int i = 1; i <= nums.length; i++) {
for (int j = 0; j < 2001; j++) {
if (dp[i - 1][j] != 0) {
dp[i][j