首页 > 编程语言 >力扣494-目标和(Java详细题解)

力扣494-目标和(Java详细题解)

时间:2024-09-13 19:52:51浏览次数:9  
标签:背包 Java target nums 题解 sum 力扣 物品 dp

题目链接:494. 目标和 - 力扣(LeetCode)

前情提要:

因为本人最近都来刷dp类的题目所以该题就默认用dp方法来做。

最近刚学完01背包,所以现在的题解都是以01背包问题为基础再来写的。

如果大家不懂01背包的话,建议可以去学一学,01背包问题可以说是背包问题的基础。

如果大家感兴趣,我后期可以出一篇专门讲解01背包问题。

dp五部曲。

1.确定dp数组和i下标的含义。

2.确定递推公式。

3.dp初始化。

4.确定dp的遍历顺序。

5.如果没有ac打印dp数组 利于debug。

每一个dp题目如果都用这五步分析清楚,那么这道题就能解出来了。

这里下文统一使用一维dp数组。

题目思路:

该题刚入手,可能会让人很懵,那么多元素,我们如何选择给每个元素添加+号还是-号。

不急,dp类的题目就是要善于找规律,找到规律,核心思路就确定了。

我们设x为整个数组添加 + 的元素和,sum - x 就是设为 - 号的元素总和。

这里的元素和不涉及符号 就是数组中添加为+的元素的和。

x-(sum - x) = tagert。

x =(tagert + sum) / 2。

得出这个结论后,我们的思路是不是就清晰许多。

数组中添加为+的元素和 = 目标整数和整个数组元素和的一半。

本题要求数组用+和-号凑成target有多少种方法。

此时问题就转化为,我们装满这个x有多少种方法

抽象出来就是x当做背包容量,nums[i]就是物品。

当我们数组中添加+的整数确定后,那添加为-号整数也就确定下来了。

大家看到(target + sum) / 2 应该担心计算的过程中向下取整有没有影响。

这么担心就对了,例如sum是5,target是2 的话其实就是无解的,所以:

if ((target + sum) % 2 == 1) return 0; // 此时没有方案

同时如果target 的绝对值已经大于sum,那么也是没有方案的。

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

接下来我们用dp五部曲来系统分析一下。

1.确定dp数组和i下标的含义。

dp[j] 就是装满j时方法的数量。

2.确定递推公式。

每个物品只有选和不选俩种状态。不选的状态就是dp[j],因为没有选,背包容量不会减少。此时就是不选当前物品时能装满的方法的数量。

选的状态就是dp[j - nums[i]],因为此时我们选择了该物品,我们就要求在装入该物品之前的装满背包的方法种类的数量然后再放入该物品。

放入该物品的状态就是dp[j - nums[i]]。

肯定有人疑问为啥不加1呢? 此时我们是选择装入该物品,首先我们得知道装入该物品之前装满的方法数量,那么加上该物品其实并不会让该方法数量加一,已经选择了该物品,所以方法数量就是dp[j - nums[i]]。

举个例子。比如我们选择了当前物品1,此时背包容量为4。

此时选择的状态就是dp[j - 1] = dp[3]。

就是装入该物品之前装满的方法数量,而此时我们其实已经选择了装入了当前物品 ,也就是说此时装满背包容量为4选择当前物品的状态就是dp[3]。

因为这个一种方法,而不是物品的数量,如果是数量,那么加入该物品肯定是要加1,但是这是一种选择方法,我已经选择了,所以就不会加1。

所以我们的递推公式就能推出,因为每个物品只有选和不选俩个状态,所以dp[j] = dp[j] + dp[j - nums[i]];

也就是当前背包容量为j的装满的方法数量,等于他不选择当前物品和选择当前物品的总方法数量。

所以再精简点就是dp[j] += dp[j - nums[i]];

3.dp初始化。

这里我们只用初始化dp[0]即可,其他的非0下标都可以由dp[0]来推出。

那么dp[0]初始化为多少呢,dp[0]其实就是当背包容量为0时,所能装满的方法数量。

背包容量为0,我们是不是能想到此时背包就是满的,因为他不能放东西嘛,所以此时对他来说也就是满的。

所以dp[0] = 1。

4.确定dp的遍历顺序。

该题与01背包的遍历顺序相同,物品从前往后遍历,背包容量从后往前遍历上为了保证每个物品只放入了一次。

5.如果没有ac打印dp数组 利于debug。

如果没有出现差错,我们就可以不用打印,因为我是写题解,所以我就不添加核心代码以外的代码,不然代码显的有些冗余。

举个例子。

在这里插入图片描述

最终代码:

class Solution {
    public int findTargetSumWays(int[] nums, int target) {
        //定义总和
        int sum = 0;
        for(int i = 0;i < nums.length;i ++)sum += nums[i];
        //如果target的绝对值大于sum,那么是没有方案的
        if (Math.abs(target) > sum) return 0;
        //如果(target+sum)除以2的余数不为0,也是没有方案的
        if ((target + sum) % 2 == 1) return 0;
        //定义背包容量
        int avg = (sum + target) / 2;
        //定义dp数组
        int[] dp = new int[avg + 1];
        //dp数组初始化
        dp[0] = 1;
        //遍历dp数组
        for(int i = 0;i < nums.length;i ++){
            for(int j = avg; j >= nums[i];j --){
                dp[j] += dp[j - nums[i]];
            }
        }
        return dp[avg];
    }
}

这一篇博客就到这了,如果你有什么疑问和想法可以打在评论区,或者私信我。

我很乐意为你解答。那么我们下篇再见!

标签:背包,Java,target,nums,题解,sum,力扣,物品,dp
From: https://blog.csdn.net/2302_79761426/article/details/142093727

相关文章

  • Java过滤map中两个 key为a和b 变成一个新的map
    在Java中,可以使用多种方法来从一个Map中提取特定键对应的条目,并将其放入新的Map中。以下是几种常见的实现方式:使用Java8及以上版本的流(Stream)使用流可以简洁地处理这个问题,并且代码易于理解。importjava.util.HashMap;importjava.util.Map;importjava.util.stream.Co......
  • java计算机毕业设计开放式实验室设备预约系统设计与实现(开题+程序+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着高等教育和科研活动的日益发展,实验室作为实践与创新的重要场所,其资源利用效率与管理水平成为衡量教育质量与科研能力的重要指标。传统实验室管理......
  • java计算机毕业设计连锁民宿平台系统(开题+程序+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着旅游业的蓬勃发展与消费者对个性化住宿体验需求的日益增长,传统酒店业正面临前所未有的挑战与机遇。连锁民宿作为新兴住宿形态,以其独特的地理位置......
  • java计算机毕业设计流浪宠物管理系统(开题+程序+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在城市化进程不断加速的今天,流浪宠物问题日益凸显,成为城市管理中不可忽视的一环。随着人们生活水平的提高和宠物文化的兴起,宠物的数量急剧增加,但由于......
  • java计算机毕业设计移动端的名医寻访平台(开题+程序+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着移动互联网技术的飞速发展,医疗健康领域正经历着前所未有的变革。传统就医模式面临挂号难、信息不对称、名医资源分配不均等痛点,尤其在偏远地区,优......
  • Java设计模式之命令模式介绍和案例示范
    一、命令模式简介命令模式(CommandPattern)是一种行为型设计模式,它将请求封装为一个对象,从而使你可以用不同的请求对客户端进行参数化、对请求排队或记录日志,以及支持可撤销的操作。命令模式的核心思想是将发出请求的对象与执行请求的对象分离,从而解耦请求的调用与处理逻辑......
  • java实现根据word模板赋值及电子签章实现
    一:添加相关依赖<!--电子签章实现<!&ndash;免费版.free只支持前三页转化&ndash;>--><dependency><groupId>e-iceblue</groupId><artifactId>spire.office.free</artifactId><......
  • JavaScript空值判断
    JavaScript本身没有判断一个变量是不是空值的函数,因为变量有可能是string,object,number,boolean等类型,类型不同,判断方法也不同。所以在文章中写了一个函数,用以判断JS变量是否空值,如果是undefined,null,'',NaN,false,0,[],{},空白字符串,都返回true,否则返回false。functionisEmpty(v){sw......
  • Java中异常的学习
    异常目录异常程序错误类型什么是异常?异常的主要作用?在实际的程序设计中,并非所有错误都能在编译期间被侦测到。运行时错误会引起异常(exception,也称例外):程序运行过程中出现的事件,它中断正常的程序控制流程。没有异常处理代码的程序,可能会非正常结束,有时候会引起严重问题。程序错......
  • Java 中实现动态代理
    在Java中,动态代理(DynamicProxy)允许在运行时创建代理对象来处理方法调用,而不需要在编译时定义具体的实现类。Java的java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口是实现动态代理的关键。步骤:创建接口:定义一个接口,代理对象将会实现这个接口......