给你一个非负整数数组 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
思路
- 首先这个题目要学会怎么通过数学转换 01背包
- 这个题目的初始化,要通过手写dp才能更加的清楚
- 要明确一点,当当前的容量为1的时候,你其实这个时候也要去考虑,因为不放也是一种解
- 其次对于math库的常见方法要熟悉,比如求指数运算
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var findTargetSumWays = function (nums, target) {
let sum = nums.reduce((a, b) => a + b);
if ((sum + target) % 2 !== 0) {
return 0
}
// 边界条件
if (Math.abs(target) > sum) return 0; // 此时没有方案
let res = (target + sum) / 2
let dp = new Array(nums.length + 1).fill(0).map(() => new Array(res + 1).fill(0))
dp[0][0] = 1;
for (let i = 0; i <= res; i++) {
dp[0][nums[0]] = 1
}
let count = 0
for (let j = 0; j < nums.length; j++) {
if (nums[j] === 0) {
count++
dp[j][0] = Math.pow(2, count)
} else {
dp[j][0] = 1
}
}
for (let i = 1; i < nums.length; i++) {
for (j = 0; j <= res; j++) {
if (j >= nums[i]) {
dp[i][j] = dp[i - 1][j] + dp[i - 1][j - nums[i]]
} else {
dp[i][j] = dp[i - 1][j]
}
}
}
return dp[nums.length - 1][res]
};