You are given a list of non-negative integers, a1, a2, ..., an, and a target, S.
Now you have 2 symbols + and -.
For each integer, you should choose one from + and - as its new symbol.
Find out how many ways to assign symbols to make sum of integers equal to target S.
Example 1:
Input: nums is [1, 1, 1, 1, 1], S is 3.
Output: 5
Explanation:
-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
There are 5 ways to assign symbols to make the sum of nums be target 3.
Note:
The length of the given array is positive and will not exceed 20.
The sum of elements in the given array will not exceed 1000.
Your output answer is guaranteed to be fitted in a 32-bit integer.
给定一个数组以及一个目标值,数组中的元素通过加或者减最终得到目标值,求所有可能情况的个数。
思路一:递归
以nums = [1, 1, 1, 1, 1], S = 3. 为例,最终要求的结果是3,数组最后一个元素是1,所以可以分为两种情况:
- [1,1,1,1] 的目标值为4,再减1得到3;
- [1,1,1,1] 的目标值为2,再加1得到3;
- 依次类推,直到只剩最后一个数字的情况。
Python 实现代码
class Solution:
def findTargetSumWays(self, nums: List[int], S: int) -> int:
res = self.helper(nums,S)
return res
def helper(self, nums, S):
l = len(nums)
if (l > 1):
# 越界,无解
if (abs(S) > sum(nums)):
res = 0
else:
# S+nums[-1]和S-nums[-1]两种情况的结果之和
res = self.helper(nums[:l-1],S+nums[-1])+self.helper(nums[:l-1],S-nums[-1])
else:
# 0特殊对待,有+0和-0结果一样
if (nums[0] == 0 and S == 0):
res = 2
elif (nums[0] == abs(S)):
res = 1
else:
res = 0
# print(nums, S, res)
return res
思路二:动态规划
问题在于选这个背包或者不选这个背包,而且每个背包只能用一次,所以就是这个背包选还是不选。那么我们就可以映射为:选加号还是选减号。又因为减号不好表示,所以我们将总数往右移。
举个例子【1,1,1,1,1】,表示为-5到5,那我们就直接映射到0到10
,变成【2,2,2,2,2】。所以背包容量为10,1表示一个背包的容量为2。
选了一个背包 10 - 2 = 8, 就还剩下8容量的背包。从0开始,值为0的方案数为1,即一个背包都不选【0,0,0,0,0】这种方案。
class Solution:
def findTargetSumWays(self, nums: List[int], S: int) -> int:
sumAll = sum(nums)
a = sumAll*2+1
if(S>=a or S+sumAll>=a):
return 0
dp = [0]*a
dp[0] = 1
for i in range(len(nums)):
nums[i]=2*nums[i]
for i in range(len(nums)):
for j in range(nums[i],a)[::-1]:
dp[j] += dp[j-nums[i]]
return dp[sumAll+S]
注意这里的a = sumAll*2+1,多加了一个1,对应了下面的dp[0] = 1。dp是一个长度为a的数组,每个位置保存对应元素和的情况个数。然后将nums的每个元素乘以2。最后的双重循环就是不断迭代求每个位置元素和的情况个数。核心代码就是里面的dp[j] += dp[j-nums[i]]
。
THE END.