494. 目标和
给定一个非负整数数组,a1, a2, ..., an, 和一个目标数,S。现在你有两个符号 +
和 -
。对于数组中的任意一个整数,你都可以从 +
或 -
中选择一个符号添加在前面。
返回可以使最终数组和为目标数 S 的所有添加符号的方法数。
示例 1:
输入: 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位整数。
解题思路:这道题难度挺大,巧妙的使用动态规划来解答。首先设P为正项和,N为负项和,那么P+N = sum(nums),P-N = S。由此可得 P = (sum(nums)+S)//2。因此若(sum(nums)+S)%2 != 0,则无解。现在我们的目标转化为在nums中选取若干数使其和为P,即(sum(nums)+S)//2。令dp[i]表示目标和为i的方法数,对于nums数组中的元素num,所有目标和为i >= num的组合数为dp[i] = dp[i] + dp[i-num]。
Python3代码如下:
class Solution(object):
def findTargetSumWays(self, nums, S):
"""
:type nums: List[int]
:type S: int
:rtype: int
"""
if sum(nums) < S:
return 0
if (sum(nums) + S) % 2 != 0:
return 0
target = (sum(nums) + S) // 2
dp = [0] * (target+1)
dp[0] = 1
for num in nums:
i = target
while i >= num:
# 目标和为i = num + (i-num)
dp[i] += dp[i-num]
i -= 1
return dp[-1]