leetCode 2915. 和为目标值的最长子序列的长度 + 动态规划 +01背包 + 空间优化 + 记忆化搜索 + 递推

news2024/11/16 13:48:55

2915. 和为目标值的最长子序列的长度 - 力扣(LeetCode)


给你一个下标从 0 开始的整数数组 nums 和一个整数 target 。返回和为 target 的 nums 子序列中,子序列 长度的最大值 。如果不存在和为 target 的子序列,返回 -1 。子序列 指的是从原数组中删除一些或者不删除任何元素后,剩余元素保持原来的顺序构成的数组。

(一)回溯 

  • f(i,j) 表示在物品集 nums 的前 i 选取物品,使得装满容量j 的背包有最多个物品
  • 也就是f(i,j) 表示在数组 nums 前 i 个的选取元素,使得这些元素之和等于 j 最长子序列长度
  • dfs(i,j) = max(dfs(i-1,j),dfs(i-1,j-nums[i])+1)
class Solution {
public:
    // 递归搜索
    int lengthOfLongestSubsequence(vector<int>& nums, int target) {
        int n = nums.size();
        function<int(int,int)>dfs=[&](int i,int s) -> int {
            if(i<0) { 
                if(s==0) return 0;
                else return INT_MIN;
            }
            return max(dfs(i-1,s),dfs(i-1,s-nums[i])+1);
        };
        int ans = dfs(n-1,target);
        return ans<0?-1:ans;
    }
};

(二) 递归搜索 + 保存计算结果 = 记忆化搜索

class Solution {
public:
    // 记忆化递归搜索
    int lengthOfLongestSubsequence(vector<int>& nums, int target) {
        int n = nums.size();
        vector<vector<int>> memo(n,vector<int>(target+1,-1));
        function<int(int,int)>dfs=[&](int i,int s) -> int {
            if(i<0) { 
                if(s==0) return 0;
                else return INT_MIN;
            }
            int& res = memo[i][s];
            if(res != -1) return res;
            if (s < nums[i]) return res = dfs(i-1,s);
            return res = max(dfs(i-1,s),dfs(i-1,s-nums[i])+1);
        };
        int ans = dfs(n-1,target);
        return ans<0?-1:ans;
    }
};
class Solution {
public:
    // 记忆化递归搜索
    int lengthOfLongestSubsequence(vector<int>& nums, int target) {
        int n = nums.size();
        vector<vector<int>> memo(n+1,vector<int>(target+1,-1));
        function<int(int,int)>dfs=[&](int i,int s) -> int {
            if(i<0) { 
                if(s==0) return 0;
                else return INT_MIN;
            }
            int& res = memo[i+1][s];
            if(res != -1) return res;

            // 不选
            int& x = memo[i][s];
            if(x == -1) x=dfs(i-1,s);
            if (s < nums[i]) return res=x;

            // 选
            int& y = memo[i][s-nums[i]];
            if(y == -1) y=dfs(i-1,s-nums[i]);
            return res = max(x,y+1);
        };
        int ans = dfs(n-1,target);
        return ans<0?-1:ans;
    }
};

(三)1:1 翻译成递推

  • dfs(i,j) = max(dfs(i-1,j),dfs(i-1,j-nums[i])+1)
  • f(i,j) = max(f(i-1,j),f(i-1,j-nums[i])+1);
  • f(i+1,j) = max(f(i,j),f(i,j-nums[i])+1);
class Solution {
public:
    // 递推
    int lengthOfLongestSubsequence(vector<int>& nums, int target) {
        int n = nums.size();
        vector<vector<int>> f(n+1,vector<int>(target+1,INT_MIN));
        f[0][0]=0;
        for(int i=0;i<nums.size();i++) {
            for(int j=0;j<=target;j++) {
                // if(j>=nums[i]) f[i+1][j] = max(f[i][j],f[i][j-nums[i]]+1);
                // else f[i+1][j] = f[i][j];
                f[i+1][j] = f[i][j];
                if(j>=nums[i]) f[i+1][j] = max(f[i][j],f[i][j-nums[i]]+1);
            }
        }
        int ans = f[n][target];
        return ans<0?-1:ans;
    }
};

进一步优化:

class Solution {
public: 
    // 递推 + 优化
    int lengthOfLongestSubsequence(vector<int>& nums, int target) {
        int n = nums.size();
        vector<vector<int>> f(n+1,vector<int>(target+1,INT_MIN));
        int sum=0;
        for(int i=0;i<nums.size();i++) {
            f[i][0]=0;
            sum=min(sum+nums[i],target);
            for(int j=1;j<=sum;j++) {
                f[i+1][j] = f[i][j];
                if(j>=nums[i]) f[i+1][j] = max(f[i][j],f[i][j-nums[i]]+1);
            }
        }
        int ans = f[n][target];
        return ans<0?-1:ans;
    }
};

>>空间优化

  • 1、二维数组空间优化
class Solution {
public:
    // 二维空间优化
    int lengthOfLongestSubsequence(vector<int>& nums, int target) {
        int n = nums.size();
        vector<vector<int>> dp(2,vector<int>(target+1,INT_MIN));
        int sum=0;
        for(int i=0;i<n;i++) {
            dp[i%2][0]=0;
            sum=min(sum+nums[i],target);
            for(int j=1;j<=sum;j++) {
                if(j >= nums[i]) dp[(i+1)%2][j] = max(dp[i%2][j],dp[i%2][j-nums[i]]+1);
                else dp[(i+1)%2][j] = dp[i%2][j];
            }
        }
        int ans = dp[n%2][target];
        return ans<0?-1:ans;
    }
};
  • 2.一维空间优化
class Solution {
public:
    // 一维空间优化
    int lengthOfLongestSubsequence(vector<int>& nums, int target) {
        int n = nums.size();
        vector<int> dp(target+1,INT_MIN);
        dp[0]=0;
        int sum=0;
        for(int i=0;i<n;i++) {
            sum=min(sum+nums[i],target);
            for(int j=sum;j>=nums[i];j--) {
                dp[j] = max(dp[j],dp[j-nums[i]]+1);
            }
        }
        int ans = dp[target];
        return ans<0?-1:ans;
    }
};

内容总结来自B站这位up主(Horn_JoJo)的视频简介:(总结得超棒!!!)

动态规划之选或者不选 通过「选」「不选」,确定子问题与原问题的联系。子问题又可以通过同样的「选」或者「不选」来再次找到子子问题与子问题的联系。这样就可以不断将问题拆成子问题。就构成了一个搜索树。当拆分到一定程度时,则找到了最容易解决的子问题。这样就可以先将子问题解决掉,然后反过来解决较大的子问题。这样就可以解决原问题了。

  • 树的根结点时原问题。树的叶子结点是边界或者最小子问题
  • 直接递归(满二叉树本,有重复子问题), 记忆化搜索(递归+记录)减少重复计算。
  • :省略递」的过程,直接「归」的过程中计算。

推荐和参考文章、视频: 

116双周赛T3复盘_哔哩哔哩_bilibiliicon-default.png?t=N7T8https://www.bilibili.com/video/BV1Zg4y197BR/?spm_id_from=333.788.top_right_bar_window_history.content.click&vd_source=a934d7fc6f47698a29dac90a922ba5a3

动态规划入门:从记忆化搜索到递推_哔哩哔哩_bilibiliicon-default.png?t=N7T8https://www.bilibili.com/video/BV1Xj411K7oF/?spm_id_from=333.788&vd_source=a934d7fc6f47698a29dac90a922ba5a3

2915. 和为目标值的最长子序列的长度 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/length-of-the-longest-subsequence-that-sums-to-target/solutions/2502839/mo-ban-qia-hao-zhuang-man-xing-0-1-bei-b-0nca/我的往期文章:

leetCode 198.打家劫舍 动态规划入门:从记忆化搜索到递推-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/weixin_41987016/article/details/134179583?spm=1001.2014.3001.5501

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

开放式耳机百元机哪个好、平价又好用的开放式耳机

开放式耳机最近一两年越来越受欢迎&#xff0c;市场上不同形态的非入耳式耳机都有&#xff0c;从骨传导&#xff0c;夹耳式到气传导等等都有。开放式耳机的好处有很多&#xff0c;非入耳式&#xff0c;不伤耳朵&#xff0c;佩戴更舒适更安全。今天就来和大家聊聊开放式耳机百元…

C语言跟着郝斌学到指针,MDK搭建了,为什么越学越不懂?

今日话题&#xff0c;一学生说C语言跟着郝斌学到指针&#xff0c;MDK搭建了&#xff0c;为什么越学越不懂&#xff1f;在学习STM32时&#xff0c;熟练使用库函数是非常关键的一步。我最初使用了野火的教材&#xff0c;虽然内容详尽&#xff0c;但对于初学者来说可能显得有些冗长…

《C语言从入门到精通》:入门容易,精通难,C语言也不例外

《C语言从入门到精通》&#xff1a;入门容易&#xff0c;精通难&#xff0c;C语言也不例外 C语言&#xff0c;容易上手&#xff0c;难以精通。它是一把双刃剑&#xff0c;既打开了编程世界的大门&#xff0c;又需要耐心与热情。无论是初学者还是专业人士&#xff0c;都需不断钻…

uniapp 离线打包 google 登录

官方文档&#xff1a; Oauth 模块 | uni小程序SDK 其中有 clientid 和反向url clientid 是 xxxx.apps.googleusercontent.com 反向url 是 com.googleusercontent.apps.xxx

早安心语微语早读,保持活力,偶尔撤退,时常欢喜,便是幸福的一生

1、单薄的人生&#xff0c;厚重的生命&#xff0c;我们总会遇到岁月的阳光和阴霾&#xff0c;路过生命的欢愉和遗憾。保持活力&#xff0c;偶尔撤退&#xff0c;时常欢喜&#xff0c;便是幸福的一生。 2、人活着不容易&#xff0c;别把自己&#xff0c;太亏欠&#xff1b;别让…

【23真题】难度Top1,没实力别硬上!

今天分享的是23年南京大学851的信号与系统试题及解析。 本套试卷难度分析&#xff1a;22年南京大学851考研真题&#xff0c;我也发布了&#xff0c;戳这里自取&#xff01;上岸平均分为105-120分&#xff01;迄今为止所做的所有23真题&#xff08;共22套&#xff09;Top1难度&…

选择适合的在线数据库设计工具,值得收藏!

最好的数据库设计工具&#xff0c;可以构建您需要任何数据库类型的数据库&#xff0c;并且可操作性简单易上手。数据库设计工具可以设计数据库架构、定义表结构、建立关系图&#xff0c;以便轻松理解数据库内容。 选择最适合你的工具 在选择数据库设计工具时&#xff0c;需要考…

【1++的Linux】之信号(二)

&#x1f44d;作者主页&#xff1a;进击的1 &#x1f929; 专栏链接&#xff1a;【1的Linux】 文章目录 一&#xff0c;信号的保存二&#xff0c;信号处理1. 信号处理的时间 一&#xff0c;信号的保存 我们在上一篇文章中讲述了信号的概念和信号的产生&#xff0c;并且我们知道…

你写的Python代码到底多快?这些测试工具了解了解

当我们写完一个脚本或一个函数&#xff0c;首先能保证得到正确结果&#xff0c;其次尽可能的快&#xff08;虽然会说Py慢&#xff0c;但有的项目就是得要基于Py开发&#xff09; 本期将总结几种获取程序运行时间的方法&#xff0c;极大的帮助对比不同算法/写法效率 插播&…

【Python工具】简介cmd安装pip及常见错误

简介cmd安装pip以及第三方库 1 检查电脑是否安装pip常用pip命令1.1 未设置环境配置1.2 未安装pip 2 常见错误2.1 Requirement already satisfied 参考 pip是Python中最常用的包管理工具&#xff0c;也是最常用的在线安装方法。 命令如下&#xff1a;package_name就是你所需要安…

软件测试报告所需周期和费用简析

软件测试报告是在软件开发和测试过程中生成的重要文档之一。它提供了对软件系统经过全面测试后的状态和质量的详细描述&#xff0c;以记录软件测试的过程和结果。 生成一个完整的测试报告需要根据软件项目的规模和复杂性来确定时间。较大规模和复杂的软件项目可能需要更长的时…

default约束

一、default约束 1、语句释义 add constraint &#xff08;添加约束&#xff09; 约束的名字 default &#xff1a;表示添加的是default约束&#xff0c;如果是外键约束就是“foreign key” 99999 for Phone&#xff1a;Phone列&#xff0c;默认值为99999 2、defualt约束效…

实时数仓-hologres使用总结

我们回顾下&#xff0c;Hologres是一款实时HSAP产品&#xff0c;隶属阿里自研大数据品牌MaxCompute&#xff0c;兼容 PostgreSQL 生态、支持MaxCompute数据直接查询&#xff0c;支持实时写入实时查询&#xff0c;实时离线联邦分析&#xff0c;低成本、高时效、快速构筑企业实时…

Wonder3D安装完美教程

话不多说,先附上地址: https://github.com/xxlong0/Wonder3D#wonder3dhttps://github.com/xxlong0/Wonder3D#wonder3d 目录 一、预览 二、环境配置

基于SSM的新枫之谷游戏攻略设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

浪潮信息“拓荒”:一场面向大模型时代的性能“压榨”

文 | 智能相对论 作者 | 沈浪 全球人工智能产业正被限制在了名为“算力”的瓶颈中&#xff0c;一侧是供不应求的高端芯片&#xff0c;另一侧则是激战正酣的“百模大战”&#xff0c;市场的供求两端已然失衡。 然而&#xff0c;大多数人的关注点仍旧还是在以英伟达为主导的高…

喜欢 Android 14 的 14 个理由

和去年 8 月中旬发布的 Android 13 正式版不同&#xff0c;今年的 Android 14 正式版延后到了 10 月 4 日——也就是 Pixel 8 系列发布的同一天。原因我们似乎也能从 Google 宣传新特性中略窥一二&#xff1a; 除了明确表示会率先向特定 Pixel 机型推送的 AI 壁纸生成&#xf…

网络层 IP协议

网络层&#xff1a;为分组交换网上的不同主机提供分组交换服务。 IP协议 协议格式 4位版本&#xff1a;ipv4就是4. 4位首部长度&#xff1a;20字节固定40字节选项。 8位服务类型&#xff1a;TOC&#xff0c;高三位表示优先级&#xff0c;已弃用&#xff0c;其次从高到底依次为…

内网穿透 cpolar

内网穿透可以使本地启动的服务让他人访问&#xff0c;不受局域网的限制。常见的是使用第三方服务&#xff0c;厉害的自己搭建。对于我这种水平来说&#xff0c;肯定是使用第三方服务。常见的 frp、ngrok、PortForward、cpolar 花生壳等等。 为什么需要内网穿透&#xff0c;因为…