Leetcode494. 目标和

相似题目:
Leetcode416. 分割等和子集
题目:
给你一个整数数组 numsnumsnums 和一个整数 targettargettarget 。
向数组中的每个整数前添加 ‘+’ 或 ‘-’ ,然后串联起所有整数,可以构造一个 表达式 :
例如,nums=[2,1]nums = [2, 1]nums=[2,1] ,可以在 2 之前添加 ‘+’ ,在 1 之前添加 ‘-’ ,然后串联起来得到表达式 “+2-1” 。
返回可以通过上述方法构造的、运算结果等于 targettargettarget 的不同 表达式 的数目。

示例 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

题解:
0-1背包问题
记数组的元素和为 sum\textit{sum}sum,添加 -\texttt{-}- 号的元素之和为 neg\textit{neg}neg,则其余添加 +\texttt{+}+ 的元素之和为 sum−neg\textit{sum}-\textit{neg}sum−neg,得到的表达式的结果为
(sum−neg)−neg=sum−2⋅neg=target(sum−neg)−neg=sum−2⋅neg=target(\textit{sum}-\textit{neg})-\textit{neg}=\textit{sum}-2\cdot\textit{neg}=\textit{target} (sum−neg)−neg=sum−2⋅neg=target(sum−neg)−neg=sum−2⋅neg=target(sum−neg)−neg=sum−2⋅neg=target

neg=sum−target2\textit{neg}=\dfrac{\textit{sum}-\textit{target}}{2}neg=2sum−target​

由于数组 nums\textit{nums}nums 中的元素都是非负整数,neg\textit{neg}neg 也必须是非负整数,所以上式成立的前提是 sum−target\textit{sum}-\textit{target}sum−target是非负偶数。若不符合该条件可直接返回 0。

若上式成立,问题转化成在数组 nums\textit{nums}nums 中选取若干元素,使得这些元素之和等于 neg\textit{neg}neg,计算选取元素的方案数。我们可以使用动态规划的方法求解。

定义二维数组 dp\textit{dp}dp,其中dp[i][j]\textit{dp}[i][j]dp[i][j] 表示从数组的 [0,i][ 0 , i ][0,i]下标范围内选取若干个正整数,使得这些元素之和等于 jjj 的方案数。假设数组 nums\textit{nums}nums 的长度为 n,则最终答案为dp[n−1][neg]\textit{dp}[n-1][\textit{neg}]dp[n−1][neg]。

在定义状态之后,需要考虑边界情况。以下两种情况都属于边界情况。

  • 如果不选取任何正整数,则被选取的正整数等于 0。因此对于所有 0≤i<n0≤i < n0≤i<n,都有dp[i][0]=1dp [ i ] [ 0 ] = 1dp[i][0]=1;
  • 当 i=0i = 0i=0 时,只有一个正整数 nums[0]\textit{nums}[0]nums[0]可以被选取,因此dp[0][nums[0]]=1dp [ 0 ] [ nums [ 0 ]] = 1dp[0][nums[0]]=1;
  • 当没有任何元素可以选取时,dp[0][j]=0(j>0)dp[0][j]=0(j>0)dp[0][j]=0(j>0)。

当 1≤i<n1 \le i < n1≤i<n时,对于数组 nums\textit{nums}nums中的第 iii 个元素 num\textit{num}num(i 的计数从 1 开始),遍历 0≤j≤neg0 \le j \le \textit{neg}0≤j≤neg,计算 dp[i][j]\textit{dp}[i][j]dp[i][j] 的值:

如果 j<numj < \textit{num}j<num,则不能选 num\textit{num}num,此时有 dp[i][j]=dp[i−1][j]\textit{dp}[i][j] = \textit{dp}[i - 1][j]dp[i][j]=dp[i−1][j];

如果 j≥numj \ge \textit{num}j≥num,则如果不选 num\textit{num}num,方案数是 dp[i−1][j]\textit{dp}[i - 1][j]dp[i−1][j],如果选 num\textit{num}num,方案数是 dp[i−1][j−num]\textit{dp}[i - 1][j - \textit{num}]dp[i−1][j−num],此时有 dp[i][j]=dp[i−1][j]+dp[i−1][j−num]\textit{dp}[i][j] = \textit{dp}[i - 1][j] + \textit{dp}[i - 1][j - \textit{num}]dp[i][j]=dp[i−1][j]+dp[i−1][j−num]。

因此状态转移方程如下:

dp[i][j]={dp[i−1][j],j<nums[i]dp[i−1][j]+dp[i−1][j−nums[i]],j≥nums[i]\textit{dp}[i][j]=\begin{cases} \textit{dp}[i - 1][j], & j<\textit{nums}[i] \\ \textit{dp}[i - 1][j] + \textit{dp}[i - 1][j - \textit{nums}[i]], & j \ge \textit{nums}[i] \end{cases}dp[i][j]={dp[i−1][j],dp[i−1][j]+dp[i−1][j−nums[i]],​j<nums[i]j≥nums[i]​

最终得到 dp[n−1][neg]\textit{dp}[n-1][\textit{neg}]dp[n−1][neg] 的值即为答案。

java代码:

  /*** @param nums* @param target* @return*/public static int findTargetSumWays(int[] nums, int target) {int len = nums.length;int sum = 0;for (int i = 0; i < len; i++) {sum += nums[i];}if ((sum - target) % 2 != 0) {return 0;}int neg = (sum - target) / 2;//dp[i][j] :在数组[0,i]中选取一些数,使得和为jint[][] dp = new int[len][neg + 1];//i=0时,只有一个正数nums[0]可以被选取dp[0][nums[0]] = 1;for (int i = 0; i < len; i++) {//从[0,i]中不选任何正整数dp[i][0] = 1;}for (int i = 1; i < len; i++) {for (int j = 1; j <= neg; j++) {if (j < nums[i]) {dp[i][j] = dp[i - 1][j];} else {dp[i][j] = dp[i - 1][j] + dp[i - 1][j - nums[i]];}}}return dp[len - 1][neg];}

Leetcode494. 目标和相关推荐

  1. Leetcode--494. 目标和

    给定一个非负整数数组,a1, a2, ..., an, 和一个目标数,S.现在你有两个符号 + 和 -.对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前面. 返回可以使最终数组和 ...

  2. c语言中dfs用pos做参数,LeetCode算法练习——深度优先搜索 DFS(2)

    更多干货就在我的个人博客 BlackBlog.tech 欢迎关注! 也可以关注我的csdn博客:黑哥的博客 谢谢大家! 我们继续LeetCode之旅. 做了一段时间的LeetCode,感觉还是不错的. ...

  3. LeetCode算法题整理(200题左右)

    目录 前言 一.树(17) 1.1.后序遍历 1.2.层次遍历 1.3.中序 1.4.前序 二.回溯(20) 2.1.普通回溯 2.2.线性回溯:组合.排列.子集.分割 2.3.矩阵回溯 三.二分查找 ...

  4. 【代码随想录】-动态规划专题

    文章目录 理论基础 斐波拉契数列 爬楼梯 使用最小花费爬楼梯 不同路径 不同路径 II 整数拆分 不同的二叉搜索树 背包问题--理论基础 01背包 二维dp数组01背包 一维数组(滚动数组) 装满背包 ...

  5. Leetcode动态规划专题(共38道)

    某一问题有很多重叠子问题 每一状态一定由上一状态推导出来 而贪心没有状态推导,而是直接选局部最优 解决方式: 确定dp数组(dp table)以及下标的含义 确定递推公式 dp数组如何初始化 确定遍历 ...

  6. Java-算法-动态规划-背包问题

    看完本篇文章可以再多练习相似题目 算法-动态规划-背包问题-附一 ​​​​​​​ 一. 背包问题介绍 1. 最原始的背包问题 给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择 ...

  7. Makefile-----GNU

    GNU Make 使用手册(中译版) 翻译:于凤昌 译者注:本人在阅读Linux源代码过程中发现如果要全面了解Linux的结构.理解Linux的编程总体设计及思想必须首先全部读通Linux源代码中各级 ...

  8. 目标和—leetcode494

    给定一个非负整数数组,a1, a2, ..., an, 和一个目标数,S.现在你有两个符号 + 和 -.对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前面. 返回可以使最终数组和 ...

  9. 浅显易懂 Makefile 入门 (03)— 目标文件搜索(VPATH 和 vpath 的区别和使用)、隐含规则

    1. 目标文件搜索(VPATH和vpath) 如果需要的文件是存在于不同的路径下(即源文件与 Makefile 文件不在同一个路径下),在编译的时候就用到了 Makefile 中为我们提供的目录搜索文 ...

最新文章

  1. 关于Messenger实现进程间通信
  2. 为什么有些xpath绝对路径拿不到数据_我写的Xpath 为什么爬取不到内容
  3. 交互 点击变色_明年旗舰机必将标配!电致变色技术解读
  4. Phoenix 原理 以及 Phoenix在HBase中的应用
  5. ThinkCMF是一款支持Swoole的开源内容管理框架,基于ThinkPHP开发,同时支持PHP-FPM和Swoole双模式,让WEB开发更快!
  6. 有用的Flex Builder快捷键
  7. python最强脚本工具_8种常用的Python工具
  8. MFC实现最小化到托盘
  9. llvm vs gcc 我被雷到了, 速度相差300多倍,你还用GCC吗!【转】
  10. 浏览器最小显示12px字体的解决方法
  11. 服务器怎么控制忽略样式_看问题要看到本质:从Web服务器说起
  12. 深度——强化学习、深度森林
  13. python填充三角形颜色怎么输入_用Python填充三角形(海龟)
  14. 如何解决Mac电脑在启动时出现空白屏幕的情况?
  15. 这几年我看过的书,力荐书单(含技术和非技术)
  16. eclipse制作app入门教程
  17. android转服务器吗,王者荣耀角色迁移iOS区可以转安卓区吗 王者荣耀角色迁移iOS区转安卓区详情...
  18. 【Linux】复制文件到当前目录 复制文件并重命名到当前目录
  19. android虹软人脸识别简书,Android 用虹软SDK做人脸识别
  20. 在UE4中实现锥体下雨效果

热门文章

  1. 六张图,看懂前瞻性数据分析,该如何做
  2. VMware虚拟机禁止防火墙启动
  3. Java线程池及配置参数详解
  4. Fluent UDF 根据给定点坐标获取cell
  5. 创新案例分享 | 构建医院绩效管理系统,助力医疗产业蓬勃发展
  6. 【统计学】【2018.05】【含源码】时间序列:以密度预测评价方法为中心的预测与评价方法
  7. React 环境搭建以及创建项目工程(一)
  8. 菜鸟在学编程__LSJ
  9. tanh函数图像以及求导
  10. Python网络爬虫实战1:百度新闻数据爬取