【算法|动态规划No.21】leetcode494. 目标和

个人主页:兜里有颗棉花糖
欢迎 点赞 收藏✨ 留言✉ 加关注本文由 兜里有颗棉花糖 原创
收录于专栏【手撕算法系列专栏】【LeetCode】
本专栏旨在提高自己算法能力的同时,记录一下自己的学习过程,希望对大家有所帮助
希望我们一起努力、成长,共同进步。
在这里插入图片描述

点击直接跳转到该题目

目录

  • 1️⃣题目描述
  • 2️⃣题目解析
  • 3️⃣解题代码

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:

输入:nums = [1], target = 1
输出:1

注意:

  • 1 <= nums.length <= 20
  • 0 <= nums[i] <= 1000
  • 0 <= sum(nums[i]) <= 1000
  • 0 <= sum(nums[i]) <= 1000

2️⃣题目解析

我们把题目中的nums数组(数组和设为sum)分为两部分,一部分是大于0的集合,和为a;另外一部分就是小于0的集合,和的绝对值为b。

根据题意可以得到关系式:

  • a + b = sum
  • a - b = target

最终可以得到a = (sum + target) / 2

至此我们就可以把问题转换为:在题目所给数组中选择一部分数使得这些数的和为a,一共有多少种选择方法。

状态表示:

  • dp[i][j]:表示从前i个数中进行挑选,和为j的所有选法。

状态转移方程:

  • dp[i][j] = dp[i - 1][j]
  • 如果j >= nums[i],则dp[i][j] = dp[i - 1][j] + dp[i - 1][j - nums[i]]

3️⃣解题代码

class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int target) {
        int n = nums.size(),sum = 0;
        for(auto x : nums) sum += x;
        int a = (sum + target) / 2;
        if(target < 0 || (sum + target) % 2) return 0;
        vector<vector<int>> dp(n + 1,vector<int>(a + 1));
        dp[0][0] = 1;
        for(int i = 1;i <= n;i++)
        {
            for(int j = 0;j <= a;j++)
            {
                dp[i][j] = dp[i - 1][j];
                if(j >= nums[i - 1]) dp[i][j] = dp[i - 1][j] + dp[i - 1][j - nums[i - 1]];
            }
        }
        return dp[n][a];
    }
};

最后就是通过啦!!!

你可能感兴趣的:(手撕算法系列专栏,LeetCode,算法,动态规划,leetcode)