力扣第494题 目标和 c++ 动态规划 c++ 01背包 难~~

这篇具有很好参考价值的文章主要介绍了力扣第494题 目标和 c++ 动态规划 c++ 01背包 难~~。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

题目

494. 目标和

中等

相关标签

数组   动态规划   回溯

给你一个非负整数数组 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

思路和解题方法

首先,代码计算了数组 nums 中所有元素的总和,并将结果保存在变量 sum 中。如果目标值 S 的绝对值大于 sum,说明无法通过改变符号使得数组元素的和等于 S,此时直接返回 0。如果 (S + sum) % 2 == 1,说明无法通过改变符号使得数组元素的和等于 S,此时直接返回 0。否则,计算背包容量 bagSize(S + sum) / 2,表示需要选择一些数,使得它们的和等于 bagSize

然后,创建一个大小为 bagSize+1 的动态规划数组 dp,并将所有元素初始化为 0。将 dp[0] 设为 1,表示当不选择任何数时,它们的和为 0,有一种方案。

接着,使用双重循环遍历数组 nums 和背包容量 bagSize。内层循环从 bagSize 开始向前遍历,每次考虑当前数是否放入背包中。如果当前数的值小于等于当前背包容量 j,则可以选择将其放入背包中,更新 dp[j] 的值为 dp[j] + dp[j - nums[i]]。这样,dp[j] 表示容量为 j 的背包所能装载的方案数。

最后,返回结果 dp[bagSize],表示选择一些数,使得它们的和等于 bagSize 的方案数。

复杂度

        时间复杂度:

                O(n*m)

        时间复杂度:O(n×m),其中 n 表示数组 nums 的长度,m 表示背包的容量,即 (S + sum) / 2。在动态规划中,我们需要遍历数组 nums 和背包容量 m,因此总时间复杂度为 O(n×m)。

        空间复杂度

                O(m)

        空间复杂度:O(m),其中 m 表示背包的容量,即 (S + sum) / 2。我们需要一个大小为 m + 1 的动态规划数组来存储中间结果,因此空间复杂度为 O(m)。

c++ 代码

class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int S) {
        // 计算数组中所有元素的总和
        int sum = 0;
        for (int i = 0; i < nums.size(); i++) sum += nums[i];
        
        // 如果目标值的绝对值大于数组元素总和,无法通过符号改变得到目标值,直接返回 0
        if (abs(S) > sum) return 0;
        
        // 如果目标值和数组元素总和的和为奇数,无法通过符号改变得到目标值,直接返回 0
        if ((S + sum) % 2 == 1) return 0;
        
        // 计算背包容量
        int bagSize = (S + sum) / 2;
        
        // 创建动态规划数组,并将所有元素初始化为 0
        vector<int> dp(bagSize + 1, 0);
        
        // 当不选择任何数时,它们的和为 0,有一种方案
        dp[0] = 1;
        
        // 使用双重循环遍历数组和背包容量
        for (int i = 0; i < nums.size(); i++) { // 遍历数组
            for (int j = bagSize; j >= nums[i]; j--) { // 遍历背包容量
                // 如果当前数的值小于等于当前背包容量,可以选择将其放入背包中
                // 更新 dp[j] 的值为 dp[j] + dp[j - nums[i]],表示容量为 j 的背包所能装载的方案数
                dp[j] += dp[j - nums[i]];
            }
        }
        
        // 返回选择一些数,使得它们的和等于背包容量的方案数
        return dp[bagSize];
    }
};

具体解释部分

1. 

if (abs(S) > sum) return 0; // 此时没有方案

if ((S + sum) % 2 == 1) return 0; // 此时没有方案
  • 第一个条件判断语句 if (abs(S) > sum) return 0; 的意思是,如果目标值 S 的绝对值大于数组 nums 中所有元素的总和 sum,那么无论如何改变符号,都无法使得数组元素的和等于目标值 S。因此,直接返回 0,表示此时没有任何方案可以满足要求。
  • 第二个条件判断语句 if ((S + sum) % 2 == 1) return 0; 的意思是,如果目标值 S 和数组 nums 中所有元素的总和 sum 的和为奇数,那么无论如何改变符号,都无法使得数组元素的和等于目标值 S。因为奇数无法通过加减操作得到偶数。所以直接返回 0,表示此时没有任何方案可以满足要求。

2. 

   int bagSize = (S + sum) / 2;
  • bagSize 表示背包的容量。由于我们要寻找一些数,使得它们的和等于目标值 S,而且我们可以通过改变符号来实现,因此我们可以将问题转化为一个经典的 0-1 背包问题。
  • 假设我们将所有正数的符号取为正号,将所有负数的符号取为负号,那么所有数的和就是 sum。我们的目标是找到一些数,使得它们的和等于目标值 S
  • 由于我们只能改变数的符号,因此我们可以将原问题转化为:从数组 nums 中选择一些数,使得它们的和等于 (S + sum) / 2。这里的 (S + sum) / 2 表示背包的容量,也就是我们要达到的目标和。

觉得有用的话可以点点赞,支持一下。

如果愿意的话关注一下。会对你有更多的帮助。

每天都会不定时更新哦  >人<  。文章来源地址https://www.toymoban.com/news/detail-741086.html

到了这里,关于力扣第494题 目标和 c++ 动态规划 c++ 01背包 难~~的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【LeetCode动态规划#07】01背包问题一维写法(状态压缩)实战,其二(目标和、零一和)

    力扣题目链接(opens new window) 难度:中等 给定一个非负整数数组,a1, a2, ..., an, 和一个目标数,S。现在你有两个符号 + 和 -。对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前面。 返回可以使最终数组和为目标数 S 的所有添加符号的方法数。 示例: 输入

    2023年04月18日
    浏览(60)
  • 动态规划 Leetcode 494 目标和

    Leetcode 494 学习记录自代码随想录 要点:1.想到±代表其实求的是连个组合的差值,进而记left为正组合,right为负组合,则有 { l e f t − r i g h t = t a r g e t l e f t + r i g h t = s u m left { begin{matrix} left-right=target \\\\ left+right=sum end{matrix} right . { l e f t − r i g h t = t a r g e t l e f t + r

    2024年04月09日
    浏览(57)
  • leetCode 2915. 和为目标值的最长子序列的长度 + 动态规划 +01背包 + 空间优化 + 记忆化搜索 + 递推

    2915. 和为目标值的最长子序列的长度 - 力扣(LeetCode) 给你一个下标从  0  开始的整数数组  nums  和一个整数  target  。返回和为  target  的  nums  子序列中,子序列  长度的最大值  。如果不存在和为  target  的子序列,返回  -1  。 子序列  指的是从原数组中删除一些

    2024年02月06日
    浏览(38)
  • 力扣:474. 一和零(动态规划)(01背包)

    给你一个二进制字符串数组 strs 和两个整数 m 和 n 。 请你找出并返回 strs 的最大子集的长度,该子集中 最多 有 m 个 0 和 n 个 1 。 如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。 示例 1 : 输入: strs = [“10”, “0001”, “111001”, “1”, “0”], m = 5, n = 3 输出:

    2024年01月22日
    浏览(35)
  • 力扣第509题 斐波那契数 新手动态规划(推荐参考) c++

    509. 斐波那契数 简单 相关标签 递归   记忆化搜索   数学   动态规划 斐波那契数  (通常用  F(n)  表示)形成的序列称为  斐波那契数列  。该数列由  0  和  1  开始,后面的每一项数字都是前面两项数字的和。也就是: 给定  n  ,请计算  F(n)  。 示例 1: 示例 2:

    2024年02月07日
    浏览(47)
  • 【Day43】代码随想录之动态规划0-1背包_1049. 最后一块石头的重量 II_494. 目标和_ 474.一和零

    动态规划理论基础 动规五部曲: 确定dp数组 下标及dp[i] 的含义。 递推公式:比如斐波那契数列 dp[i] = dp[i-1] + dp[i-2]。 初始化dp数组。 确定遍历顺序:从前到后or其他。 打印。 出现结果不正确: 打印dp日志和自己想的一样:递推公式、初始化或者遍历顺序出错。 打印dp日志和

    2024年02月22日
    浏览(48)
  • 力扣第131题 分割回文串 c++ 回溯+简单 动态规划(是否为回文子串)

    131. 分割回文串 中等 相关标签 字符串   动态规划   回溯 给你一个字符串  s ,请你将   s   分割成一些子串,使每个子串都是  回文串  。返回  s  所有可能的分割方案。 回文串  是正着读和反着读都一样的字符串。 示例 1: 示例 2: 提示: 1 = s.length = 16 s  仅由小写

    2024年02月07日
    浏览(44)
  • 力扣第96题 不同的二叉搜索树 c++ 二叉搜索树 动态规划 + 数学思维

    96. 不同的二叉搜索树 中等 相关标签 树   二叉搜索树   数学   动态规划   二叉树 给你一个整数  n  ,求恰由  n  个节点组成且节点值从  1  到  n  互不相同的  二叉搜索树  有多少种?返回满足题意的二叉搜索树的种数。 示例 1: 示例 2: 提示: 1 = n = 19 vectorint

    2024年02月06日
    浏览(35)
  • 力扣算法刷题Day42|动态规划:01背包问题 分割等和子集

    力扣题目:01背包问题(二维数组) 刷题时长:参考题解 解题方法:动态规划 + 二维dp数组 复杂度分析 时间 空间 问题总结 理解递推公式困难 本题收获 动规思路:两层for循环,第一层i遍历物品,第二层j枚举背包容量以内所有值 确定dp数组及下标的含义:dp[i][j] 表示从下标

    2024年02月13日
    浏览(59)
  • C++ 动态规划 01背包问题

    有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。 第 i 件物品的体积是 vi ,价值是 wi 。 求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。 输出最大价值。 输入格式 第一行两个整数, N,V ,用空格隔开,分别表示物品数量和背

    2024年04月27日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包