494. 目标和
难度中等767收藏分享切换为英文接收动态反馈
给你一个整数数组 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
示例 2:
输入:nums = [1], target = 1
输出:1
提示:
1 <= nums.length <= 20
0 <= nums[i] <= 1000
0 <= sum(nums[i]) <= 1000
-1000 <= target <= 100
递归解法
解法1 暴力递归 超时了
class Solution:
def findTargetSumWays(self, nums: List[int], S: int) -> int:
positive = 0
negative = 0
cur_result = []
level = 0
self.result = []
self._generate(nums, S, positive, negative, cur_result, level)
return len(self.result)
pass
def _generate(self, nums: List, target, positive: int, negative: int, cur_result: List, level: int):
# terminator
if positive + negative == len(nums):
if sum(cur_result) == target:
self.result.append(cur_result.copy())
return
# current logic process
cur_result.append(nums[level])
# drill down
self._generate(nums, target, positive + 1, negative, cur_result, level + 1)
# reverse the current level status
cur_result.pop(-1)
# current logic process
cur_result.append(-nums[level])
# drill down
self._generate(nums, target, positive, negative + 1, cur_result, level + 1)
# reverse the current level status
cur_result.pop(-1)
pass
解法2 暴力递归
超时了
class Solution:
"""
时间复杂度:O(2^n)
"""
def findTargetSumWays(self, nums: List[int], S: int) -> int:
cur_result = 0
level = 0
return self._dfs(nums, cur_result, level, S)
def _dfs(self, nums: List, cur: int, level, target: int):
if level == len(nums):
return 1 if cur == target else 0
left = self._dfs(nums, cur + nums[level], level + 1, target)
right = self._dfs(nums, cur - nums[level], level + 1, target)
return left + right
动态规划
注意题目中有要求 0< nums[i]<1000
所以这里 可以使用dp 进行求解
dp[i][target] 表示 去前i个元素 构成target的数目
初始化第一个元素
dp[0][target] =1
n = len(nums)
total = sum(nums)
n为nums的长度
dp的维度 row * col = (n+1) * (2*total+1)
状态转义方程:
dp[i+1][j] = dp[i][j-nums[i]] + dp[i][j+ nums[i]]
看下代码 实现:
from typing import List
class Solution:
"""
https://www.bilibili.com/video/BV1WW411C7Mp/
"""
def findTargetSumWays(self, nums: List[int], target: int) -> int:
total = sum(nums)
# 值范围超过了sum的值范围 则无法得到
if target > total:
return 0
n = len(nums)
offset = total
# dp = (n+1) * (2*total+1)
dp = [[0] * (2 * total + 1) for _ in range(n + 2)]
dp[0][offset] = 1
for i in range(0, n):
j = nums[i]
while j < 2 * total + 1 - nums[i]:
# dp process
if dp[i][j]:
dp[i + 1][j + nums[i]] += dp[i][j]
dp[i + 1][j - nums[i]] += dp[i][j]
j += 1
return dp[n][offset + target]
参考文档