Leetcode 494. 目标和(Target Sum)

Leetcode 494.目标和

1 题目描述(Leetcode题目链接

  给定一个非负整数数组,a1, a2, …, an, 和一个目标数,S。现在你有两个符号 + 和 -。对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前面。
  返回可以使最终数组和为目标数 S 的所有添加符号的方法数。

输入: nums: [1, 1, 1, 1, 1], S: 3
输出: 5
解释: 

-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

一共有5种方法让最终目标和为3

注意:

  • 数组非空,且长度不会超过20。
  • 初始的数组的和不会超过1000。
  • 保证返回的最终结果能被32位整数存下。

2 题解

  最先想到的方法是递归方法,但是提交的时候直接就超时了。进行一些适当的变换,将其转换为01背包问题来做貌似才是此题的本意。
  首先设 P P P n u m s nums nums中所有前面加正号的数的集合, N N N n u m s nums nums中所有前面加负号的数的集合,那么我们就像要找到满足下式的集合数量(即 P P P的数量):
S = s u m ( P ) − s u m ( N ) S = sum(P)-sum(N) S=sum(P)sum(N)
现在左右两边同时加上 s u m ( P ) + s u m ( N ) sum(P) + sum(N) sum(P)+sum(N)得到:
S + s u m ( P ) + s u m ( N ) = 2 ∗ s u m ( P ) S + sum(P) + sum(N) = 2*sum(P) S+sum(P)+sum(N)=2sum(P)
因此:
s u m ( P ) = ( S + s u m ( n u m s ) ) / 2 sum(P) = (S+sum(nums))/2 sum(P)=(S+sum(nums))/2
那么问题就转化为: n u m s nums nums中有多少个子集满足其和等于 s u m ( P ) sum(P) sum(P),也就是01背包问题即向容量为 s u m ( P ) sum(P) sum(P)的背包里面装东西,有多少种方法恰好能装满。为此我们定义 D P DP DP数组长度为 s u m ( P ) + 1 sum(P) + 1 sum(P)+1 D P [ i ] DP[i] DP[i]表示当容量为 i i i,装前 j j j个物品的方法数,因此状态转移方程为:
D P [ i ] = D P [ i ] + D P [ i − n u m s [ j ] ] DP[i] = DP[i] + DP[i-nums[j]] DP[i]=DP[i]+DP[inums[j]]

class Solution:
    def findTargetSumWays(self, nums: List[int], S: int) -> int:
        if (S + sum(nums))%2 == 1 or sum(nums) < S:
            return 0
        capacity = (S + sum(nums))//2
        DP = [0] * (capacity + 1)
        DP[0] = 1
        for j in range(len(nums)):
            for i in range(capacity, -1, -1):
                if i < nums[j]:
                    break;
                DP[i] += DP[i - nums[j]]
        return DP[capacity]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值