494.目标和

https://leetcode-cn.com/problems/target-sum/

一:暴力遍历(回溯)

py超时,但java没有

从0开始递归数组,直到n位置终止,每次分别回溯尝试+和-

class Solution:
    def findTargetSumWays(self, nums, target: int) -> int:
        self.res = 0	#全局计数
        def bt(start, sum):
            if start  == len(nums):	#递归出口
                if sum == target:
                    self.res += 1	#满足条件,结果加一
                return
            #注意不要直接修改sum,即“保存现场”
            bt(start+1, sum+nums[start])	#加号
            bt(start+1, sum-nums[start])	#减号
        #开始
        bt(0, 0)
        return self.res

二:dp

记数组的元素和为sum,添加-号的元素之和为neg,则其余添加 + 的元素之和为sum-neg。由题意,有:

(sum−neg)−neg = sum−2*neg = target

neg = (sum−target)/2

题目中nums元素非负,因此neg也非负,当sum−target为负直接返回0

问题转化成在数组 nums 中选取若干元素,使得这些元素之和等于 neg,计算选取元素的方案数。是一个01背包问题,可以用dp

与416. 分割等和子集类似,设dp[i][j] 表示在数组nums 的前 i个数中选取元素,使得这些元素之和等于 j 的方案数,i=0表示不取,因此i=1表示数组0号元素,即dp[i][j]表示能否用数组[0...i-1]凑出,dp方程为

base case:

最终所求为dp[n][neg](n为nums长度)

最后更新于