动态规划--LC494.目标和

在这里插入图片描述
此类问题与传统的01背包问题稍有不同,尤其是状态转移方程。01背包问题会有max(),求一个最大;而此问题求的是能有多少种方法,面对第i个元素,存在取与不取的问题,最后加起来就是所有的方法。

class Solution(object):
    def findTargetSumWays(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        # 这个题问的是有多少种方法,跟01背包还有点不同,01背包求最大,会有max()
        # 假设所有前面是‘+’的整数和为P,前面是‘-’的整数和为N
        # 则P+N=SUM,P-N=target,两式可得P=(SUM+target)/2,SUM和target都是可以计算得到的固定值
        # 此时可以将问题转化为01背包问题:
        # dp[i][j]:在数组nums前i个数字种选取元素,使这些元素之和等于j的方案数。
        # 首先分析特殊情况:nums为整数数组,所以P肯定为整数,则(SUM+target)/2为整数,也就是(SUM+target)能被2整除,如果不能被2整除就是有问题。再一个如果target的绝对值大于sum也肯定是有问题
        # 状态转移方程:
        # 1.当nums[i] > j 时,dp[i][j]=dp[i-1][j]
        # 2.当nums[i] <= j 时,可以选择是否取nums[i]
        # 不取nums[i]:dp[i][j]=dp[i-1][j]
        # 取num[i]:dp[i][j]=dp[i-1][j-nums[i]]
        # 所以2的dp[i][j]应该是两者的相加,因为我们求得是由多少种方法
        # 因此,dp[i][j]=dp[i-1][j]+dp[i-1][j-nums[i]]
        # 初始化:
        # dp[0][0]=1,没有任何元素可以选择时,和只能为0
        # dp[0][j]=0,j>0
        # 遍历顺序,01背包问题都是先物品,后背包,此时应为先元素,后和
        sum_ = sum(nums)
        # 前面是‘+’的整数和
        sump = (sum_+target)/2
        if abs(target)>sum_ or (sum_+target) % 2 == 1:
            return 0
        dp = [[0 for _ in range(sump+1)] for _ in range(len(nums)+1)]
        # 初始化,j为0,不管是否有元素,都只有一种方法就是
        for i in range(len(nums)+1):
            dp[i][0]=1 
        for i in range(1, len(nums)+1):
            for j in range(sump+1):
                if j >= nums[i-1]:
                    dp[i][j] = dp[i-1][j] + dp[i-1][j-nums[i-1]]
                else:
                    dp[i][j] = dp[i-1][j]
        return dp[-1][-1]
class Solution(object):
    def findTargetSumWays(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        # 优化,使用数组解决
        sum_ = sum(nums)
        # 前面是‘+’的整数和
        sump = (sum_+target)/2
        if abs(target)>sum_ or (sum_+target) % 2 == 1:
            return 0
        dp = [0 for _ in range(sump+1)]
        # 装满容量为0的背包,有1种方法,就是装0件物品
        dp[0] = 1 
        for i in range(1, len(nums)+1):
            for j in range(sump, -1, -1):
                if j >= nums[i-1]:
                    dp[j] = dp[j] + dp[j-nums[i-1]]
        return dp[-1]
class Solution {
    int count = 0;

    public int findTargetSumWays(int[] nums, int target) {
        backtrack(nums, target, 0, 0);
        return count;
    }

    public void backtrack(int[] nums, int target, int index, int sum) {
        if (index == nums.length) {
            if (sum == target) {
                count++;
            }
        } else {
            backtrack(nums, target, index + 1, sum + nums[index]);
            backtrack(nums, target, index + 1, sum - nums[index]);
        }
    }
}

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/target-sum/solution/mu-biao-he-by-leetcode-solution-o0cp/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值