力扣-494目标和(dp)

力扣-494目标和

1、题目

给你一个整数数组 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、分析

  1. 题目。首先看到这个题目,我们想到的是回溯法,通过穷举进行暴力找到所有组合,回溯三部曲。但是回溯往往是指数级别的时间复杂度,所以往往超时,这个题不能够选择,所以我们可以从中使用动态规划01背包问题。

  2. 01背包问题。首先我们得知道我们的背包容量,可能我们刚开始以为这个target是这个背包问题的容量,然后来求,但是这个求得是多个nums[i]最接近target的值,但与我们的这个题目的不同表达式的数目结果输出不一致。所以我们得转换思想,重新定义。

    首先可以来分析,在这个"+“或”-"的过程,要想得到这个target,就是其中的和部分-减部分=target和部分+减部分=sum,所以我们可以得到和部分-(sum-和部分)=target,即和部分=(sum+target)/2。至此,我们知道sum和target是常量,也就是和部分也是一个已知的。

  3. 动态方程。我们通过上面可以知道和部分可以求出来,也就是我们可以从中得到的计算部分和值,设置为我们需要的背包容量size。dp[i]表示的是部分和为i时不同表达式的数目,如果背包容量size为5的话,那么当nums[i]为1的时候,就有dp[4]种不同的方法,因为是所有数量,所以应该是累加的一个过程。所以我们可以得到我们的递推公式dp[j] += dp[j - nums[i]]

  4. 边界值。如例1,当我们dp[1]的时候,我们的这个递推公式需要dp[0]的值,我们可以试验几次,从中可以得出我们需要的dp[0]=1。然后就是使用一维dp数组求解01背包问题。

  5. 符合值。我们的和部分可见是(sum+target)/2得到的,所以我们的和部分应该是一个整数,因为题目所有的数都应该是整数,所以这里可以加一个判断,不符合的直接返回0。其次,我们应该还考虑到这个整数值是不是负数的情况,然后是否符合我们能够求出的值结果。

  6. 书写代码。

3、代码及分析

class Solution {
    public int findTargetSumWays(int[] nums, int target) {
        // 1.根据这题首先联想到回溯,其次想到动态规划dp,01背包问题
        // 2.设和为x,减为sum-x,有sum和target,可得x=(sum+target)/2
        // 3.dp[i]表示运算的 结果等于target 的 不同数量
        int sum = 0;
        for (int i = 0; i < nums.length; i++){
            sum += nums[i];
        }
        if (target > sum || (sum + target) % 2 == 1) return 0;
        if (target < 0 && sum < -target) return 0;
        int size = (sum + target) / 2;
        if (size < 0) size = -size;
        int[] dp = new int[size + 1];
        dp[0] = 1;

        for (int i = 0; i < nums.length; i++){
            for (int j = size; j >= nums[i]; j--){
                dp[j] += dp[j - nums[i]];
            }
        }

        return dp[size];
        
    }
}

4、练习

力扣题目链接:https://leetcode.cn/problems/target-sum/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值