每日OJ题_01背包③_力扣494. 目标和(dp+滚动数组优化)
目录
力扣494. 目标和
问题解析
解析代码
滚动数组优化代码
力扣494. 目标和
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
提示:
1 <= nums.length <= 20
0 <= nums[i] <= 1000
0 <= sum(nums[i]) <= 1000
-1000 <= target <= 1000
class Solution {
public:int findTargetSumWays(vector<int>& nums, int target) {}
};
问题解析
本题可以直接用暴搜的方法解决。但是稍微用数学知识分析⼀下,就能转化成常见的背包模型问题。
设我们最终选取的结果中,前面加 + 号的数字之和为 a ,前面加 - 号的数字之和为 b ,整个数组的总和为 sum ,于是有:
- a + b = sum
- a - b = target
上面两个式子消去 b 之后,可以得到 a = (sum + target) / 2 ,也就是说,我们仅需在 nums 数组中选择一些数,将它们凑成和为 (sum + target) / 2 即可。问题就变成了力扣416. 分割等和子集这道题。 可以用相同的分析模式,来处理这道题。
以某个位置为结尾,结合题目要求,定义一个状态表示:
dp[i][j] 表示:在前 i 个数中选,总和正好等于 j ,一共有多少种选法。
状态转移方程:
dp 状态转移方程分析方式,一般都是根据最后一步的状况,来分情况讨论:
- 不选择 nums[i] :那么我们凑成总和 j 的总方案,就要看在前 i - 1 个元素中选,凑成总和为 j 的方案数。根据状态表示,此时 dp[i][j] = dp[i - 1][j] ; 。
- 选择 nums[i] :这种情况下是有前提条件的,此时的 j 应该是大于等于 nums[i]。 因为如果这个元素都比要凑成的总和大,那选择它就没有意义。那么能够凑成总和为 j 的方案数,就要看在前 i - 1 个元素中选,能否凑成总和为 j - nums[i] 。根据 状态表示,此时 dp[i][j] = dp[i - 1][j - nums[i]] ; (j >= nums[i] )。
综上,两种情况如果存在的话,应该要累加在⼀起。因此,状态转移方程为: if(j >= nums[i - 1]) dp[i][j] = dp[i - 1][j] + dp[i - 1][j - nums[i]] ; else dp[i][j] = dp[i - 1][j] ;(如果多加一行一列,找原数组下标要减1)
初始化:多加一行一列,方便初始化,由于需要用到上一行的数据,因此可以先把第一行初始化。 第一行表示不选择任何元素,要凑成目标和 j 。只有当目标和为 0 的时候才能做到,因此第一行仅需初始化第一个元素 dp[0][0] = 1。
填表顺序:根据状态转移方程,需要从上往下填写每一行,每一个的顺序是任意的。
返回值:根据状态表示,返回 dp[n][a] 的值。 其中 n 表示数组的大小, target 表示要凑成的目标和。
解析代码
class Solution {
public:int findTargetSumWays(vector<int>& nums, int target) {int sum = 0, n = nums.size();;for(auto& e : nums){sum += e;}int a = (sum + target) / 2;if(a < 0 || (sum + target) % 2) // 小于0或者除不尽return 0;vector<vector<int>> dp(n + 1, vector<int>(a + 1, 0));dp[0][0] = 1;for(int i = 1; i <= n; ++i){for(int j = 0; j <= a; ++j) // 第1列用到dp[0][0]初始化{if(j >= nums[i - 1])dp[i][j] = dp[i - 1][j] + dp[i - 1][j - nums[i - 1]];elsedp[i][j] = dp[i - 1][j];}}return dp[n][a];}
};
滚动数组优化代码
背包问题基本上都是利用滚动数组来做空间上的优化:(时间也有常数的优化)
- 利用滚动数组优化。
- 直接在原始代码上修改。
在01背包问题中,优化的结果为:
- 删掉所有的横坐标。
- 修改一下 j 的遍历顺序。
(滚动数组优化代码只需能在原代码上修改就行,不用考虑什么状态表示)
class Solution {
public:int findTargetSumWays(vector<int>& nums, int target) {int sum = 0, n = nums.size();;for(auto& e : nums){sum += e;}int a = (sum + target) / 2;if(a < 0 || (sum + target) % 2) // 小于0或者除不尽return 0;vector<int> dp(a + 1, 0);dp[0] = 1;for(int i = 1; i <= n; ++i){for(int j = a; j >= nums[i - 1]; --j) // 滚动数组优化{dp[j] += dp[j - nums[i - 1]];}}return dp[a];}
};
相关文章:

每日OJ题_01背包③_力扣494. 目标和(dp+滚动数组优化)
目录 力扣494. 目标和 问题解析 解析代码 滚动数组优化代码 力扣494. 目标和 494. 目标和 难度 中等 给你一个非负整数数组 nums 和一个整数 target 。 向数组中的每个整数前添加 或 - ,然后串联起所有整数,可以构造一个 表达式 : …...

vue3+element plus图片预览点击按钮直接显示图片的预览形式
1 需求 直接上需求: 我想要直接点击下面这个“预览”按钮,然后呈现出预览图片的形式 ok,需求知道了,下面让我们来看看如何实现吧 ~ 2 实现 template部分 <el-buttontype"primary"size"small"click&qu…...

GAMS104 现代游戏引擎 2
渲染的难点可以分为一下三部分:如何计算入射光线、如何考虑材质以及如何实现全局光照。 渲染的难点之一在于阴影,或者说是光的可见性。如何做出合适的阴影效果远比想象中要难得多,在实践中往往需要通过大量的技巧才能实现符合人认知的阴影效…...

spring boot学习第十七篇:OAuth2概述及使用GitHub登录第三方网站
0. 导言 我们在浏览器上可以访问成百上千个网站,使用每个网站的服务一般都要先注册账号,那么我们为了更好地记忆,一般都会在多个网站使用相同的账号和密码进行注册。那么问题就来了,如果在你注册的网站中有某些个网站的系统设计不…...
基于springboot的电影评论网站系统源码数据库
基于springboot的电影评论网站系统源码数据库 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了电影评论网站的开发全过程。通过分析电影评论网站管理的不足,创建了一个计算机管理电影评论网站的方案。文…...

javaScript手写专题——实现instanceof/call/apply/bind/new的过程/继承方式
目录 原型链相关 手写instanceof 实现一个_instance方法,判断对象obj是否是target的实例 测试 手写new的过程 实现一个myNew方法,接收一个构造函数以及构造函数的参数,返回构造函数创建的实例对象 测试myNew方法 手写类的继承 ES6&…...
C++11 新特性:tuple 元组
std::tuple是 C11 中引入的一个非常强大的类型,它允许将多个类型不同的值,组合成单一对象。 std::tuple非常适合用于那些需要返回多个值的场景,而且它的灵活性和通用性使得其成为现代 C 编程中不可或缺的一部分。下面,我们将探讨…...

最齐全,最简单的免费SSL证书获取方法——实现HTTPS访问
一:阿里云 优势:大平台,在站长中知名度最高,提供20张免费单域名SSL证书 缺点:数量有限,并且只有单域名证书,通配符以及多域名没有免费版本。并且提供的单域名证书只有三个月的期限。 二&#…...

c语言->贪吃蛇实战技巧结合EasyX简单实现页面管理(简单实现)
✅作者简介:大家好,我是橘橙黄又青,一个想要与大家共同进步的男人😉😉 🍎个人主页:再无B~U~G-CSDN博客 1. 游戏背景 贪吃蛇是久负盛名的游戏,它也和俄罗斯⽅…...

C语言-详解内存函数
文章目录 1.memcpy使用和模拟实现1.1 memcpy函数的使用规则1.2 memcpy函数的使用1.2 模拟实现memcpy函数 2.memmove 函数的使用和模拟实现2.1 memmove 函数使用规则2.2 memmove函数的使用2.3 模拟实现memmove函数2.3.1 从后往前移2.3.2 从前往后移 2.4 算法实现2.4.1 从前往后移…...

【核心完整复现】基于目标级联法的微网群多主体分布式优化调度
1 主要内容 之前发布了华电学报的复现程序《基于目标级联法的微网群多主体分布式优化调度》,具体链接为【防骗版】基于目标级联法的微网群多主体分布式优化调度,虽然对模型及结果进行了复现,但是部分模型细节和参数并没有完全实现࿰…...
Mac下安装NVM,NVM安装Node(附带NPM)
1、理解NVM、node、NPM 什么是NVM? NVM: Node.js Version Manager,用来管理 node 的版本。 什么是 Node.js? Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。 Node.js使用了一个事件驱动、非阻塞式I/O的模型( Node.js的特性&…...
java之变量的作用域
在java中,变量需要像其他编程语言中先定义,再使用。但并不是定义好就能用。需要对变量定义一个作用范围才能使用,这个作用范围称为作用域。 在java程序中,变量会定义在一个花括号内,花括号内的区域就是作用域。 比如…...
CentOS 7软件安装全攻略:YUM命令详解与实战
在CentOS 7中,软件安装主要依赖于其强大的包管理器——YUM(Yellowdog Updater Modified)。YUM可以自动解决软件包之间的依赖关系,使得软件的安装、更新和卸载变得简单而高效。本文将详细介绍CentOS 7中软件安装的相关命令、选项和…...

达梦关键字(如:XML,EXCHANGE,DOMAIN,link等)配置忽略
背景:在使用达梦数据库时,查询SQL中涉及XML,EXCHANGE,DOMAIN,link字段,在达梦中是关键字,SQL报关键词不能使用的错误。 解决办法: 配置达梦安装文件E:\MyJava\dmdbms\data\DAMENG\dm.ini 忽略这些关键词,…...

2024/4/11 直流电机调速/PWM
一、直流电机简介和PWM原理 直流电机是一种将电能转换为机械能的装置。一般的直流电机有两个电极,当电极正接时,电机正转,当电极反接时,电机反转 直流电机主要由永磁体(定子)、线圈(转子&…...

贝乐虎儿歌v6.8.0解锁高级版亲子学习儿歌
软件介绍 贝乐虎儿歌免费版app,出自乐擎网络的创意工坊,专为孩子们雕琢了一系列富含创意的动画儿歌内容。这款app通过贝乐虎兄弟的可爱形象,让孩子们在愉快的观看中接触到各种儿歌和故事。不仅如此,app还巧妙地将古诗、英语等学习…...
计算机网络技术-RIP、0SPF和BGP协议的工作原理和应用
目录 RIP (Routing Information Protocolv)路由信息协议OSPF(Open Shortest Path First) 开放式最短路径优先BGP( Border Gateway Protocol)边界网关协议 RIP (Routing Information Protocolv)路由信息协议 RIP协议 是 TCP/IP环境中开发的第一个路由选择…...

机器学习——自动驾驶
本章我们主要学习以下内容: 阅读自动驾驶论文采集数据根据论文搭建自动驾驶神经网络训练模型在仿真环境中进行自动驾驶 论文介绍 本文参考自2016年英伟达发表的论文《End to End Learning for Self-Driving Cars》 📎end2end.pdf...
Android 14 vold 分析(2)VolumeManager 和 NetlinkManger
3. VolumeManager::Instance() 和 VolumeManager::start() system/vold/VolumeManager.cpp 3.1 Instance()没啥好说的 非常简单 112 VolumeManager* VolumeManager::Instance() {113 if (!sInstance) sInstance new VolumeManager();114 return sInst…...

基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...

高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...

Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...

算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...

JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...

【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...