【题解 | 01背包】和为目标值的最长子序列的长度

2024-04-02 01:44

本文主要是介绍【题解 | 01背包】和为目标值的最长子序列的长度,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

和为目标值的最长子序列的长度

力扣:2915. 和为目标值的最长子序列的长度

给你一个下标从 0 开始的整数数组 nums 和一个整数 target

返回和为 targetnums 子序列中,子序列 长度的最大值 。如果不存在和为 target 的子序列,返回 -1

子序列 指的是从原数组中删除一些或者不删除任何元素后,剩余元素保持原来的顺序构成的数组。

示例 1:

输入:nums = [1,2,3,4,5], target = 9
输出:3
解释:总共有 3 个子序列的和为 9 :[4,5][1,3,5][2,3,4] 。
最长的子序列是 [1,3,5][2,3,4] 。所以答案为 3 。

示例 2:

输入:nums = [4,1,3,2,1,5], target = 7
输出:4
解释:总共有 5 个子序列的和为 7 :[4,3][4,1,2][4,2,1][1,1,5][1,3,2,1] 。
最长子序列为 [1,3,2,1] 。所以答案为 4 。

示例 3:

输入:nums = [1,1,5,4,5], target = 3
输出:-1
解释:无法得到和为 3 的子序列。

提示:

  • 1 <= nums.length <= 1000
  • 1 <= nums[i] <= 1000
  • 1 <= target <= 1000

解题

这道题可以使用动态规划和01背包的思想,并进行空间压缩,减少空间复杂度。

首先定义dp数组,其中dp[j]表示和为j的子序列的最大长度。初始时,除了dp[0]0,其余的dp[j]都被设置为Integer.MIN_VALUE,表示不可能得到和为j的子序列。

然后,对于数组nums中的每一个数num,我们都尝试更新dp[j],其中j的范围是[num, s]s是当前所有数的和与target的较小值。对于每一个j,我们可以选择使用num或者不使用num

  • 如果我们使用num,那么dp[j]就等于dp[j - num] + 1
  • 如果我们不使用num,那么dp[j]就保持不变。

我们选择这两者的较大值作为新的dp[j]

最后,如果dp[target]大于0,我们返回dp[target],否则我们返回-1,表示不存在和为target的子序列。

参考代码:

class Solution {public int lengthOfLongestSubsequence(List<Integer> nums, int target) {int[] dp = new int[target + 1];Arrays.fill(dp, Integer.MIN_VALUE);dp[0] = 0;int s = 0;for (int num : nums) {s = Math.min(s + num, target);for (int j = s; j >= num; j--) {dp[j] = Math.max(dp[j], dp[j - num] + 1);}}return dp[target] > 0 ? dp[target] : -1;}
}

注意,在动态规划的过程中我们有一个小优化,就是没有枚举到整个target,我们是从 s 开始遍历,s是当前所有数的和与target的较小值,也就是说枚举到当前所有数的和即可。

说白了就是,如果当前所有数的和都没有达到target,那么我们就没有必要去尝试更新和大于当前所有数的和的dp[j],因为这些dp[j]是不可能被更新的,可以减少不必要的计算。

这篇关于【题解 | 01背包】和为目标值的最长子序列的长度的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/868658

相关文章

MySQL 获取字符串长度及注意事项

《MySQL获取字符串长度及注意事项》本文通过实例代码给大家介绍MySQL获取字符串长度及注意事项,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录mysql 获取字符串长度详解 核心长度函数对比⚠️ 六大关键注意事项1. 字符编码决定字节长度2

全面解析MySQL索引长度限制问题与解决方案

《全面解析MySQL索引长度限制问题与解决方案》MySQL对索引长度设限是为了保持高效的数据检索性能,这个限制不是MySQL的缺陷,而是数据库设计中的权衡结果,下面我们就来看看如何解决这一问题吧... 目录引言:为什么会有索引键长度问题?一、问题根源深度解析mysql索引长度限制原理实际场景示例二、五大解决

利用Python实现时间序列动量策略

《利用Python实现时间序列动量策略》时间序列动量策略作为量化交易领域中最为持久且被深入研究的策略类型之一,其核心理念相对简明:对于显示上升趋势的资产建立多头头寸,对于呈现下降趋势的资产建立空头头寸... 目录引言传统策略面临的风险管理挑战波动率调整机制:实现风险标准化策略实施的技术细节波动率调整的战略价

PostgreSQL 序列(Sequence) 与 Oracle 序列对比差异分析

《PostgreSQL序列(Sequence)与Oracle序列对比差异分析》PostgreSQL和Oracle都提供了序列(Sequence)功能,但在实现细节和使用方式上存在一些重要差异,... 目录PostgreSQL 序列(Sequence) 与 oracle 序列对比一 基本语法对比1.1 创建序

Java实现按字节长度截取字符串

《Java实现按字节长度截取字符串》在Java中,由于字符串可能包含多字节字符,直接按字节长度截取可能会导致乱码或截取不准确的问题,下面我们就来看看几种按字节长度截取字符串的方法吧... 目录方法一:使用String的getBytes方法方法二:指定字符编码处理方法三:更精确的字符编码处理使用示例注意事项方

C++从序列容器中删除元素的四种方法

《C++从序列容器中删除元素的四种方法》删除元素的方法在序列容器和关联容器之间是非常不同的,在序列容器中,vector和string是最常用的,但这里也会介绍deque和list以供全面了解,尽管在一... 目录一、简介二、移除给定位置的元素三、移除与某个值相等的元素3.1、序列容器vector、deque

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

关于最长递增子序列问题概述

《关于最长递增子序列问题概述》本文详细介绍了最长递增子序列问题的定义及两种优化解法:贪心+二分查找和动态规划+状态压缩,贪心+二分查找时间复杂度为O(nlogn),通过维护一个有序的“尾巴”数组来高效... 一、最长递增子序列问题概述1. 问题定义给定一个整数序列,例如 nums = [10, 9, 2

poj2576(二维背包)

题意:n个人分成两组,两组人数只差小于1 , 并且体重只差最小 对于人数要求恰好装满,对于体重要求尽量多,一开始没做出来,看了下解题,按照自己的感觉写,然后a了 状态转移方程:dp[i][j] = max(dp[i][j],dp[i-1][j-c[k]]+c[k]);其中i表示人数,j表示背包容量,k表示输入的体重的 代码如下: #include<iostream>#include<

hdu2159(二维背包)

这是我的第一道二维背包题,没想到自己一下子就A了,但是代码写的比较乱,下面的代码是我有重新修改的 状态转移:dp[i][j] = max(dp[i][j], dp[i-1][j-c[z]]+v[z]); 其中dp[i][j]表示,打了i个怪物,消耗j的耐力值,所得到的最大经验值 代码如下: #include<iostream>#include<algorithm>#include<