LeetCode494. 目标和

494. 目标和

文章目录

    • [494. 目标和](https://leetcode.cn/problems/target-sum/)
      • 一、题目
      • 二、题解
        • 方法一:目标和路径计数算法
        • 方法二:01背包
        • 方法三:01背包一维数组


一、题目

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

二、题解

方法一:目标和路径计数算法

思考过程可以分为以下几步:

  1. 问题拆解: 首先,将问题拆解为更小的子问题。在这个问题中,我们可以将目标和问题拆解为在给定数组中选择一些数字,使得它们的和等于目标值。

  2. 状态定义: 确定动态规划的状态。在这个问题中,我们可以考虑使用二维数组 dp[i][j] 表示在前 i 个数字中,和为 j 的表达式的数量。

  3. 状态转移方程: 找到状态之间的转移关系。这是动态规划问题的核心。在这个问题中,对于每个数字 nums[i],我们有两种选择:添加正号或者添加负号。因此,状态转移方程可以表示为:dp[i][j] = dp[i-1][j-nums[i]] + dp[i-1][j+nums[i]],即前 i-1 个数字和为 j-nums[i] 的表达式数量加上前 i-1 个数字和为 j+nums[i] 的表达式数量,最后的数字是dp[i][j] = dp[i-1][abs(j-nums[i])] + dp[i-1][j+nums[i]],因为如果j < nums[i],我们是可以通过dp[i-1][nums[i]-j]得到dp[i][j]。举个例子,如图,为什么dp[2][0] = 2?图中已经说明白了。

在这里插入图片描述

  1. 边界条件: 根据问题的实际情况,确定边界条件。在这个问题中,我们可以从第一个数字开始考虑,初始化 dp[0][j],表示只有一个数字时,和为 j 的表达式数量。

  2. 问题求解: 根据状态转移方程和边界条件,从小问题逐步求解到原问题。填充二维数组 dp,最终 dp[nums.size()-1][abs(target)] 就是我们要的答案,表示在所有数字中,和为 target 的表达式数量。

class Solution {
public:int findTargetSumWays(vector<int>& nums, int target) {// 定义一个二维数组 dp,大小为 (nums.size(), 2001),其中 dp[i][j] 表示在前 i 个数字中,和为 j 的表达式数量vector<vector<int>> dp(nums.size(), vector<int>(2001, 0));// 初始化:处理只有一个数字的情况for(int i = 0; i <= 1000; i++){if(nums[0] == i){if(nums[0] == 0) dp[0][i] = 2;  // 对于数字 0,可以有正号或负号else dp[0][i] = 1;}}// 填写 dp 数组for(int i = 1; i < nums.size(); i++){for(int j = 0; j <= 1000; j++){dp[i][j] = dp[i-1][abs(j-nums[i])] + dp[i-1][j+nums[i]];  // 根据状态转移方程计算 dp[i][j]}}return dp[nums.size()-1][abs(target)];  // 返回在所有数字中,和为 target 的表达式数量}
};

方法二:01背包

01背包问题通常是这样的:给定一组物品,每个物品有重量和价值,我们要选择一些物品放入一个容量有限的背包中,使得背包中物品的总重量不超过背包的容量,同时最大化物品的总价值。

在这道题中,我们可以将正数部分和负数部分(前面是加号的和前面是减号的)的数字分别看作两组物品。正数部分的数字相当于具有正的价值,负数部分的数字相当于具有负的价值。

具体步骤如下:

  1. 将数组 nums 拆分成两个子数组:addminusadd 包含所有正数部分的数字,minus 包含所有负数部分的数字。

    我们可以得到add-minus = targetadd+minus = sum,从而根据这两个式子得出(sum+target)/2 = add

  2. 使用01背包的思想:这个问题就转化成了所有数字凑成add这个数的方法。即背包容量是add,物品是nums数组里的所有元素。

  3. 使用动态规划来解决问题:我们创建一个二维数组 dp,其中 dp[i][j] 表示在考虑前 i 个物品时,总和等于 j 的方法数。

    • 初始化 dp[0][0] 为 1,因为当没有物品可选时,总和为 0 是唯一的一种方式;但如果nums[0] = 0,还有一种方式就是只取nums[0],则有两种方式。
    • 对于其它物品 nums[i],我们根据以下规则更新 dp[i][j]
      • 如果 j >= nums[i],那么我们可以选择是否将 nums[i] 放入背包,dp[i][j]等于不放入背包和放入背包方式的总和,即 dp[i][j] = dp[i-1][j] + dp[i-1][j-nums[i]]
      • 如果 j < nums[i],则nums[i]不可以放入背包dp[i][j] = dp[i-1][j]
  4. 最终的答案是 dp[nums.size()-1][add],表示在考虑所有物品后,总和等于 add 的方法数。

class Solution {
public:int findTargetSumWays(vector<int>& nums, int target) {int sum = 0;// 计算数组nums的总和for(int i = 0; i < nums.size(); i++){sum += nums[i];}// 如果总和与目标值之和为奇数,或者总和小于目标值的绝对值,则无解,返回0if((sum + target) % 2 == 1 || sum < abs(target)){return 0;}// 计算要构造的正数部分和,这是01背包问题中的背包容量int add = (sum + target) / 2;// 创建二维动态规划数组dpvector<vector<int>> dp(nums.size(),vector<int>(add+1, 0));// 初始化dp数组for(int i = 0; i <= add; i++){// 如果i等于第一个数字nums[0],表示可以用第一个数字构造和为i的方式有1种if(i == nums[0]){dp[0][i] = 1;}} // 特殊情况处理if(nums[0] == 0) dp[0][0] = 2;// 普通情况:当没有物品可选时,总和为 0 是唯一的一种方式else dp[0][0] = 1;// 填写dp数组for(int i = 1; i < nums.size(); i++){for(int j = 0; j <= add; j++){// 如果当前数字nums[i]大于目标和j,无法用当前数字构造if(nums[i] > j) dp[i][j] = dp[i-1][j];// 选择是否将 `nums[i]` 放入背包,`dp[i][j]`等于不放入背包和放入背包方式的总和else dp[i][j] = dp[i-1][j] + dp[i-1][j-nums[i]];}}// 返回最终的结果,即在考虑所有数字后,构造和为add的方法数return dp[nums.size()-1][add];}
};

方法三:01背包一维数组

具体细节就是初始化这里,这个dp[0] = 1相当于是按照结论推初始化(因为按照二维的初始化方式是错误的),最好还是去理解一下二维的吧……

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/118977.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

外部中断(EXTI) - 按键控制LED

一、外部中断/事件控制器(EXTI)结构图 1、结构图分析 外部中断主要由外部中断/事件控制器(External interrupt/event controller, EXTI)控制&#xff0c;它管理了外部中断或者事件的使能与否、触发方式等功能。 &#xff08; 外部中断/事件控制器(EXTI)结构图 &#xff09; …

【5】openGL使用宏和函数进行错误检测

当我们编写openGL程序&#xff0c;没有报编译链接错误&#xff0c;但是运行结果是黑屏&#xff0c;这不是我们想要的。 openGL提供了glGetError 来检查错误&#xff0c;我们可以通过在运行时进行打断点查看glGetError返回值&#xff0c;得到的是一个十进制数&#xff0c;将其转…

Nacos服务注册和服务配置

Nacos 是什么 Nacos (Dynamic Naming and Configuration Service)&#xff0c;其命名由三部分组成&#xff1a; Na (naming/nameServer)&#xff0c;即服务注册中心。 co (configuration)&#xff0c;即配置中心。 s (service)&#xff0c;即服务&#xff0c;表示 Nacos 实现的…

华为 连接OSPF和RIP网络---OSPF和RIP网络相互引入

路由引入简介 不同路由协议之间不能直接共享各自的路由信息&#xff0c;需要依靠配置路由的引入来实现。 获得路由信息一般有3种途径&#xff1a;直连网段、静态配置和路由协议。可以将通过这3种途径获得的路由信息引入到路由协议中&#xff0c;例如&#xff0c;把直连网段引入…

【文心一言】学习笔记

学习资料 《听说文心一言App霸榜了&#xff0c;那必须来一波全方位实测了》 情感陪伴&#xff1a;文心一言 App 可以充当用户的情感树洞&#xff0c;提供知心姐姐、【暖男】等角色扮演&#xff0c;为用户提供情绪疏导、情感分析、约会建议等服务。 1. 模型属性 【提示词工具…

无涯教程-Android - CheckBox函数

CheckBox是可以由用户切换的on/off开关。为用户提供一组互不排斥的可选选项时,应使用复选框。 CheckBox 复选框属性 以下是与CheckBox控件相关的重要属性。您可以查看Android官方文档以获取属性的完整列表以及可以在运行时更改这些属性的相关方法。 继承自 android.widget.T…

nuxt3+ts+vue3的ssr项目总结

目录 一、什么是SSR、SEO、SPA&#xff0c;它们之间的关系又是怎样的。 二、VUE做SSR的几种方法 1、插件prerender-spa-plugin 2、VUE开启SSR渲染模式 3、使用NUXT框架 三、NUXT3VUE3TS &#xff08;一&#xff09;基本配置 1、文件夹介绍 assets components pages…

Docker安装MySQL教程

虽然 docker 安装 mysql 不是一个很好的方案&#xff0c;但是为了个人使用方便&#xff0c;使用 docker 安装 mysql 还是没什么问题的。 本文为了方便&#xff0c;我们直接通过yum方式安装。所以&#xff0c;我们在安装之前需要电脑可以联网&#xff0c;不然我们这种方式是安装…

Python的由来和基础语法(一)

目录 一、Python 背景知识 1.1Python 是咋来的? 1.2Python 都能干啥? 1.3Python 的优缺点 二、基础语法 2.1常量和表达式 2.2变量和类型 变量的语法 (1) 定义变量 (2) 使用变量 变量的类型 (1) 整数 (2) 浮点数(小数) (3) 字符串 (4) 布尔 (5) 其他 动态类型…

《TCP/IP网络编程》阅读笔记--基于Windows实现Hello Word服务器端和客户端

目录 1--Hello Word服务器端 2--客户端 3--编译运行 3-1--编译服务器端 3-2--编译客户端 3-3--运行 1--Hello Word服务器端 // gcc hello_server_win.c -o hello_server_win -lwsock32 // hello_server_win 9190 #include <stdio.h> #include <stdlib.h> #i…

vue+element-ui el-table组件二次封装实现虚拟滚动,解决数据量大渲染DOM过多而卡顿问题

一、此功能已集成到TTable组件中 二、最终效果 三、需求 某些页面不做分页时&#xff0c;当数据过多&#xff0c;会导致页面卡顿&#xff0c;甚至卡死 四、虚拟滚动 一、固定一个可视区域的大小并且其大小是不变的&#xff0c;那么要做到性能最大化就需要尽量少地渲染 DOM 元素…

kotlin 转 Java

今天突然想研究下有些kotlin文件转为Java到底长什么样&#xff0c;好方便优化kotlin代码&#xff0c;搞了半天发现一个非常简单的Android Studio或者Intellij idea官方插件Kotlin&#xff0c;Kotlin是插件的名字&#xff0c;真是醉了&#xff1b; 这里以AS为例&#xff0c;使用…

OTFS-ISAC通信最新进展

测试场景 Tx DD域帧结构导频区域 Rx DD域帧导频区域 原始星座图 信道估计及数据检测 经过MP算法后的星座图 误码率曲线

ELK安装、部署、调试 (二) ES的安装部署

ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎&#xff0c;基于RESTful web接口操作ES&#xff0c;也可以利用Java API。Elasticsearch是用Java开发的&#xff0c;并作为Apache许可条款下的开放源码发布&#xff0c;是当前流行的企业…

windows-nessus安装

1、下载 路径&#xff1a;Download Tenable Nessus | Tenable 2、获取active code 路径&#xff1a;Tenable Nessus Essentials Vulnerability Scanner | Tenable 3、安装 challenge code:上图马赛克位置 active code:获取active code第二张图片的马赛克位置 4、激活 5、安装…

CTFhub-文件上传-.htaccess

首先上传 .htaccess 的文件 .htaccess SetHandler application/x-httpd-php 这段内容的作用是使所有的文件都会被解析为php文件 然后上传1.jpg 的文件 内容为一句话木马 1.jpg <?php echo "PHP Loaded"; eval($_POST[a]); ?> 用蚁剑连接 http://ch…

SpringCloudAlibaba OpenFeign整合及详解

SpringCloudAlibaba OpenFeign 在前面&#xff0c;我们使用Nacos服务注册发现后&#xff0c;服务远程调用可以使用RestTemplateRibbon或者OpenFeign调用。实际开发中很少使用RestTemplate这种方式进行调用服务&#xff0c;每次调用需要填写地址&#xff0c;还要配置各种的参数&…

软件测试/测试开发丨Pytest和Allure报告 学习笔记

点此获取更多相关资料 本文为霍格沃兹测试开发学社学员学习笔记分享 原文链接&#xff1a;https://ceshiren.com/t/topic/26755 Pytest 命名规则 类型规则文件test_开头 或者 _test 结尾类Test 开头方法/函数test_开头注意&#xff1a;测试类中不可以添加__init__构造函数 注…

使用 BERT 进行文本分类 (03/3)

一、说明 在使用BERT&#xff08;2&#xff09;进行文本分类时&#xff0c;我们讨论了什么是PyTorch以及如何预处理我们的数据&#xff0c;以便可以使用BERT模型对其进行分析。在这篇文章中&#xff0c;我将向您展示如何训练分类器并对其进行评估。 二、准备数据的又一个步骤 …

IDEA中Run/Debug Configurations添加VM options和Program arguments

1. 现象描述 我在我的IDEA当中打开配置模板后&#xff0c;发现没有VM options和Program arguments&#xff0c;也就是虚拟机选项和程序实参这两项&#xff0c;导致我不能配置系统属性参数和命令行参数&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff0…