494. 目标和(Java)(回溯递归)(动归迭代,背包问题)

33 篇文章 0 订阅
15 篇文章 0 订阅

1 题目

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

返回可以使最终数组和为目标数 S 的所有添加符号的方法数。

示例 1:

输入: 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位整数存下。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/target-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2 Java

2.1 方法一(回溯递归)

class Solution {
    public int findTargetSumWays(int[] nums, int S) {
        if(nums.length == 0){
            if(S == 0)  return 1;
            return 0;
        }
        function(nums, S, 0, 0);
        return ans;
    }

    // 记录结果
    int ans = 0;
    // 回溯递归
    public void function(int[] nums, int S, int index, int curS){
        // if判断 是否符合条件,若符合则计入结果
        if(index == nums.length){
            if(curS == S)   ans++;
            return;
        }
        // for循环 多路选择
        function(nums, S, index + 1, curS + nums[index]);
        function(nums, S, index + 1, curS - nums[index]);
    }
}

2.2 !方法二(动归迭代,背包问题)

class Solution {
    public int findTargetSumWays(int[] nums, int S) {
        // dp[i][j] 代表 当加减到nums的索引i这个元素(包括该元素),结果为j的方案数量

        // 创建dp,初始化
        int[][] dp = new int[nums.length][2001];
        dp[0][nums[0] + 1000] = 1;
        dp[0][- nums[0] + 1000] += 1;   // 神坑!!!如果nums[0]是0,则这两行都是dp[0][1000],所以应该是dp[0][1000] = 2

        // 外层for 状态步进
        for(int i = 1; i < nums.length; i++){
            // 内层for 多路择优
            for(int j = -1000; j < 1001; j++){
                // 需要判断索引是否溢出,即该值是否可达(题目说了nums元素和 <= 1000)
                if(j + 1000 - nums[i] >= 0 )    dp[i][j + 1000] += dp[i - 1][j + 1000 - nums[i]];
                if(j + 1000 + nums[i] < 2001)   dp[i][j + 1000] += dp[i - 1][j + 1000 + nums[i]];
            }
        }

        return S > 1000 ? 0 : dp[nums.length - 1][S + 1000];
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值