dp:01背包,目标和,一和零

目标和

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

返回可以使最终数组和为目标数 S 的所有添加符号的方法数。

示例:

输入:nums: [1, 1, 1, 1, 1], S: 3 输出:5 解释:

-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

一共有5种方法让最终目标和为3。

提示:

数组非空,且长度不会超过 20 。
初始的数组的和不会超过 1000 。
保证返回的最终结果能被 32 位整数存下。

思路

  • 转换成01背包问题
    考虑到每个数字不管是取正数还是取负数,都只能取一次,所以考虑使用01背包解决
  • 可以转换一下,设有正数值为 x ,那么负数的数值就为 sum-x ,可以列出等式x-(sum-x) = S,所以x = (s+sum)/2 问题也就转换成了装满容量为x的背包,有几种方法 也就是说target = bagSize = x
  • 本题还需特判:当S>sum时,肯定没有方法,如果x不为整数,也不符合题目要求

分五步走:

  1. 确定dp数组及其下标含义:dp[j]表示装满容量为j的背包的方法数
  2. 推导dp公式:不考虑nums[i]的情况下,有dp[j-nums[i]]中方法(个人理解不考虑nums[i],相当于nums[i]是一个负数,不算进正数)
    考虑到nums[i].就有dp[j]种方法.
    所以dp[j] = dp[j] + dp[j-nums[i]]
  3. 初始化dp数组:dp[0] = 1,因为背包容量为0时,也可以有装入0个物品这一种方法
  4. 确定遍历方向:dp[j] 由 dp[j-nums[i]] 推出,所以遍历方向是从左往右,先遍历物品,再倒序遍历背包容量
  5. 举例推导dp数组

代码

public int findTargetSumWays(int[] nums, int S) {
   
    int sum = 0;
    for(int i=0;i<nums.length;i++) sum 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值