题目
给你一个整数数组 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
**分析:**直观的解法是用回溯法,罗列出每一种可能性,每一个数都有"+"和”-“两种情况,因此就是一个二叉树的遍历问题,求出每一个从顶点到底部路径和,记录和为target的数量。每一个数都有两种状态,共有n个数,因此时间复杂度为 2 n 2^n 2n,指数爆炸。见方法1
方法1:
class Solution:
def findTargetSumWays(self, nums: List[int], target: int) -> int:
n = len(nums)
count = 0
def backtrack(k, s, count):
if k == n:
if s == target:
count += 1
return count
for op in [-1, 1]:
num = op*nums[k]
count = backtrack(k+1, s+num, count)
return count
return backtrack(0, 0, count)
class Solution:
def findTargetSumWays(self, nums: List[int], target: int) -> int:
"""
假设添加“+”的元素和为pos, 添加“-”的元素和为seg, sum为list的元素和,
有pos+seg=sum, pos-seg=target ==> pos = (sum+target)/2
"""
n = len(nums)
s1 = sum(nums)
s2 = s1+target
#pos必然为整数, 因此没有整除说明不存在满足的表达式
if s2 % 2 != 0 or s2 < 0:
return 0
else:
pos = s2 // 2
dp = [[0]* (pos+1) for i in range(n+1)]
dp[0][0] = 1
for i in range(1, n+1):
for t in range(pos+1):
if t < nums[i-1]:
dp[i][t] = dp[i-1][t]
else:
dp[i][t] = dp[i-1][t-nums[i-1]] + dp[i-1][t]
return dp[-1][-1]