Skip to content

LeetCode-494-目标和

题目

给定一个非负整数数组,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 位整数存下。

解题思路

方法1、回溯:

每一步选择都有该位置数的正负2种选择方案,画成树状图可以知道需要DFS遍历2棵树

1棵树以第1位数为正开始寻找,1棵树以第1位数为负开始寻找,找到符合要求的答案。

类似于暴力穷举。

当遍历的深度达到数组长度,且路径和等于S的时候,说明找到了一条路径,count++

当不满足路径和要求时,返回上一层,进行回溯,撤销上一次的选择。

方法2、动态规划:

详见https://leetcode-cn.com/problems/target-sum/solution/494-mu-biao-he-by-ming-zhi-shan-you-m9rfkvkdad/

Java代码1

java
class Solution {
    int res = 0;
    int count = 0;
    public int findTargetSumWays(int[] nums, int S) {
        int len = nums.length;
        backtrack(0,nums,S,len);
        return count;
    }

    public void backtrack(int i,int[] nums,int S,int len){
        if(i==len){
            if(res==S){
                count++;
            }
            return;
        }
        // 选择正号
        res+=nums[i];
        backtrack(i+1,nums,S,len);
        // 撤销选择
        res-=nums[i];
        
        // 选择负号
        res-=nums[i];
        backtrack(i+1,nums,S,len);
        // 撤销选择
        res+=nums[i];
    }
}

Java代码2

java

class Solution{
    public int findTargetSumWays(int[] nums, int S){
        if(nums.length == 0) return 0;
        int sum = 0;
        for(int i = 0; i < nums.length; i++) sum += nums[i];
        if (Math.abs(S) > Math.abs(sum)) return 0;
        int[][] dp = new int[nums.length][sum*2+1];
        if(nums[0] == 0) dp[0][sum] = 2;
        else{
            dp[0][sum+nums[0]] = 1;
            dp[0][sum-nums[0]] = 1;
        }
        
        for(int i = 1; i<nums.length; i++){
            for(int j = 0; j<(sum*2+1);j++){
                int l = (j - nums[i]) >= 0 ? j - nums[i] : 0;
                int r = (j + nums[i]) < (sum*2+1) ? j + nums[i] : 0;
                dp[i][j] = dp[i-1][l] + dp[i-1][r];
            }
        }
        return dp[nums.length-1][sum+S];
    }
}