- 题目要求:
-
思路:
- 画一个表格
- 可以求出数组中所有元素的和为5,所以画一个(5*2+1)len(nums)的表格(也就是一个二维数组)
- -5~5表示把这个数组每一个元素加上或减去得到结果值的所有可能
- 从[-1 -1 -1 -1 -1]到[+1 +1 +1 +1 +1]的所有可能
- 遍历数组,当遍历到数组下标为0的元素时,也就是第一个1,它与加号减号的组合有两种:1 和 -1,所以得到-1的方法有1种,得到1的方法也有一种
- 当遍历到数组下标为1的元素时,前面已经得到的可能的结果值为-1和1,那么在这个基础上,新加入新的1与加号减号的组合,可能得到-2(-1-1),可能得到0(-1+1或+1-1),可能得到2(+1+1),所以在-2的位置有一种方法,在0的位置有2种,在1的位置有1种
- 依次遍历,遍历到最后,找到目标值所对应的列的最后一行,也就是3所对应的有5中方法,返回5即可
-
要特殊注意:
- 当数组的第一个元素为0时,应初始化0的位置方法为2,因为0+0=0,0-0=0
- 核心代码:
dp = [[0 for i in range(2 * total + 1)] for j in range(len(nums))]
# 如果数组的第一个元素为0,那么+0或是-0,结果都为0
if nums[0] == 0:
dp[0][total] = 2
else:
# total是数组元素的和,也是dp的行中,元素值为0的元素的下标
dp[0][total + nums[0]] = 1
dp[0][total - nums[0]] = 1
for i in range(1, len(dp)):
for j in range(len(dp[0])):
# 注意边界
# 在第一个图中,dp[4][0]的当前元素值是1,对应的目标值是-5,那么-5加上或减去1可能是上一行得到的值,但是要注意-5-1也就是-6不在考虑范围内
# left和right都初始化为0,是因为在表格也就是二维数组中,0所在的列所对应的目标值是给定数组的所有元素可能得到的最小值,是一个极值,所以不到最后一行,也就是不遍历到最后一个数组元素是得不到这个值的,也就是,所有行的下标为0的位置(所有行的起始位置)的方法数一定是0,所以当left或right越界了,没有被赋新的值时,不会影响计算方法数
left, right = 0, 0
if j - nums[i] >= 0:
left = j - nums[i]
if j + nums[i] < 2 * total + 1:
right = j + nums[i]
dp[i][j] = dp[i - 1][left] + dp[i - 1][right]
return dp[-1][total + S]
- 完整代码:
class Solution:
def findTargetSumWays(self, nums: List[int], S: int) -> int:
total = sum(nums)
if total < S:
return 0
dp = [[0 for i in range(2 * total + 1)] for j in range(len(nums))]
if nums[0] == 0:
dp[0][total] = 2
else:
dp[0][total + nums[0]] = 1
dp[0][total - nums[0]] = 1
for i in range(1, len(dp)):
for j in range(len(dp[0])):
left, right = 0, 0
if j - nums[i] >= 0:
left = j - nums[i]
if j + nums[i] < 2 * total + 1:
right = j + nums[i]
dp[i][j] = dp[i - 1][left] + dp[i - 1][right]
return dp[-1][total + S]
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。