题目
给定一个非负整数数组,a1,a2, … , an,和一个目标数,S。现在你有两个符号+ 和 -。对于数组中任意一个整数,你都可以从 + 和 - 中选择一个符号添加在前面。
返回可以使最终数组和为目标数S的所有添加符号的方法数。
思路
思路一:深度优先搜索策略(回溯法)
class Solution:result = 0def findTargetSumWays(self, nums: List[int], S: int) -> int:if len(nums) == 0: return 0self.backtrack(nums, i = 0, S)# i表示第i个元素return self.result# 回溯法模板def backtrack(self, nums, i, rest):# i表示第i个元素# base caseif i == len(nums):if rest == 0:self.result += 1return# 给nums[i]选择 - 号rest += nums[i]# 穷举 nums[i + 1]self.backtrack(nums, i +1, rest)# 撤销选择rest -= nums[i]# 给nums[i] 选择 + 号rest -= nums[i]self.backtrack(nums, i + 1, rest)rest += nums[i]
复杂度分析
- 时间复杂度:O(2^N),其中 NN 是数组
nums的长度。 - 空间复杂度:O(N),为递归使用的栈空间大小。
更优雅的实现
class Solution:count = 0def findTargetSumWays(self, nums: List[int], S: int) -> int:self.calculate(nums, 0, 0, S)return self.countdef calculate(self, nums, i, Sum, target):if i == len(nums):if Sum == target:self.count += 1else:self.calculate(nums, i + 1, Sum + nums[i], target)self.calculate(nums, i + 1, Sum - nums[i], target)
思路二:动态规划
还没搞懂
系统学了动态规划再看
这道题是一道常见的背包问题。
状态变量:dp[i][j]:数组中前i个元素,组成和为j的方案数。
转移方程:
dp[i][j] = dp[i - 1][j - nums[i]] + dp[i - 1][j + nums[i]]
class Solution:def findTargetSumWays(self, nums: List[int], S: int) -> int:if not nums: return 0dp = [0] * (target + 1)dp[0] = 1 # 凑够目标i一共有dp[i]中方法for i in range(1, target + 1):for num in nums:if i >= num:dp[i] += dp[i - num]return dp[target]
- todo
https://leetcode-cn.com/problems/target-sum/solution/python-dfs-xiang-jie-by-jimmy00745/
class Solution:def findTargetSumWays(self, nums: List[int], S: int) -> int:if sum(nums) < S or (sum(nums) + S) % 2 == 1: return 0P = (sum(nums) + S) // 2dp = [1] + [0 for _ in range(P)]for num in nums:for j in range(P,num-1,-1):dp[j] += dp[j - num]return dp[P]
