LC494.目标和
1. 题目
给你一个非负整数数组 nums
和一个整数 target
。
向数组中的每个整数前添加'+'
或 '-'
,然后串联起所有整数,可以构造一个 表达式 :
- 例如,
nums = [2, 1]
,可以在2
之前添加'+'
,在1
之前添加'-'
,然后串联起来得到表达式"+2-1"
。
返回可以通过上述方法构造的、运算结果等于 target
的不同 表达式 的数目。
示例 1:
markdown
**输入:** 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:
markdown
**输入:** nums = [1], target = 1
**输出:** 1
提示:
1 <= nums.length <= 20
0 <= nums[i] <= 1000
0 <= sum(nums[i]) <= 1000
-1000 <= target <= 1000
2. 思路
- 本质上就是把数组分成两个部分,假定第一个部分的总和是
sum1
,第二个部分的总和是sum2
,那么sum1 + sum2 = allSum && sum1 - sum2 = target
- 那么,
sum1
的和实际上是一个确切的值,该问题就变成一个01
背包问题,01
背包求方案数。 - 本质:从数组当中挑选一些数字,能够组成一个值。
3. 代码
go
func findTargetSumWays(nums []int, target int) int {
// sum1 - sum2 = target
// sum1 + sum2 = all
// sum1 = (target + all) / 2
all := 0
for _, v := range nums {
all += v
}
if (all + target) % 2 != 0 || (all + target) < 0{
return 0
}
sum1 := (all + target) / 2
f := make([]int, sum1 + 1)
// 01 package
f[0] = 1
for i := range nums {
curVol := nums[i]
for k := sum1; k >= curVol; k-- {
f[k] = f[k] + f[k - curVol]
}
}
return f[sum1]
}