【动态规划】子序列问题II|最长定差子序列|最长的斐波那契数列的长度|最长等差数列|等差数列的划分

news2025/1/21 8:51:51

一、最长定差子序列

1218. 最长定差子序列

算法原理:

💡细节:

1.正常创建dp表,分析状态转移方程:可能b存在于多个不同的位置,那么要用哪个下标的dp呢?

用最后一个b的,因为用前面的可能后面还存在c可以满足条件(a-b=b-c)

2.优化1:那么多b值,那么普通查找只能从后面开始一个一个找,为了提高效率,可以将b+dp[j]的值放入哈希表中

3.优化2:既然都将dp值放入哈希表中,那么可以直接不用new一个dp表,直接在哈希表中做动态规划,这样也同样有下标对应,只是由数组变为哈希表(k,v)

4.初始化为最小值

class Solution {
    public int longestSubsequence(int[] arr, int difference) {
        Map<Integer,Integer> hash = new HashMap<>();//分别放arr[i],dp[i]

        int ret = 1;
        for(int a:arr) {
            hash.put(a,hash.getOrDefault(a-difference,0)+1);
            ret = Math.max(ret,hash.get(a));
        }

        return ret;

    }
}

 二、最长的斐波那契数列的长度

873. 最长的斐波那契子序列的长度

算法原理:

💡细节: 

1.如果只用一维数组表示dp,肯定是表示不出来的,当一维dp去找前一个数字nums[j]的时候,由于dp表示的是这个位置结尾的最长长度,并不知道倒数第二个斐波那契数的位置,所以需要多一个参数表示

2.优化:通过b,c去找a的时候,需要遍历数组,为了提高效率,将下标和对应的元素放入哈希表中

3.初始化:虽然可能结果为0,但是直接初始化为2,可以少考虑状态转移方程两种情况,同时这样处理要注意返回值处理

class Solution {
    public int lenLongestFibSubseq(int[] arr) {
        //哈希表优化
        Map<Integer,Integer> hash = new HashMap<>();
        int n = arr.length;
        for(int i=0;i<n;i++) hash.put(arr[i],i);

        int[][] dp = new int[n][n];
        //初始化
        for(int i=0;i<n;i++) 
            for(int j=0;j<n;j++) 
                dp[i][j] = 2;

        int ret =2;
        for(int j=2;j<n;j++) {//最后一个数得从第3个位置开始
            for(int i=1;i<n;i++) {//倒数第二个数得从第2个位置开始
                int a = arr[j]-arr[i];//第一个数的大小
                if(a<arr[i]&&hash.containsKey(a)) {
                    dp[i][j] = dp[hash.get(a)][i] + 1;
                }
                ret = Math.max(ret,dp[i][j]);
            }
        }

        return ret<3?0:ret;
    }
}

三、最长等差数列

1027. 最长等差数列

算法原理:

 💡细节: 

1.同上题一样,一维dp数组只能知道长度,不知道等差数列啥样,所以需要多开一个参数,用两个数来确定第一个数的位置

2.状态转移方程的确定:分三种情况,第一个数a是否存在+a存在是否在b(第二个数)的左边

(1)a存在&&a在b的左边 ->dp[i][j] = dp[k][i] +1(其中k为第一个数的下标,需要在数组中找)

(2)a存在but a在b的右边-> dp = 2(由于dp的设置,只要两个不同的值i和j)

(3)a不存在 -> dp = 2

3.遍历优化:找k下标的方式O(n**3)优化

(1)第一种优化方式:在dp之前,将<元素,下标数组>放入哈希表中->可行,但是当数组下标太多,那么还是趋于O(n**3)

(2)第二种优化方式:一边dp,一边保存<元素,i下标>放入哈希表,注意第一个数遍历不到,需要在遍历之前先加入哈希表

4.填表方式:两种方式,先确定倒数第一个数,或者先确定倒数第二个数

but这里只能先确定倒数第二个数i,因为需要考虑dp之前hash表中的元素,因为k需要<i,所以不能将元素太早加入hash表中,要找i之前的k(所以这里的k需要是i下标之前的哈希表)

class Solution {
    public int longestArithSeqLength(int[] nums) {
        int n = nums.length;

        Map<Integer,Integer> hash = new HashMap<>();//<元素,下标>
        hash.put(nums[0],0);

        int[][] dp = new int[n][n];

        //初始化
        for(int i=0;i<n;i++) 
            Arrays.fill(dp[i],2);
        
        int ret = 2;
        for(int i=1;i<n;i++) {//固定倒数第一个数
            for(int j=i+1;j<n;j++) {//固定倒数第二个数
                int a = 2*nums[i]-nums[j];//第一个数
                if(hash.containsKey(a)) {
                    dp[i][j]=dp[hash.get(a)][i]+1;
                    ret = Math.max(ret,dp[i][j]);
                }
            }
            hash.put(nums[i],i);//每次i换位置就将(nums[i],i)放入哈希表
        }
        return ret;
    }
}

四、等差数列的划分

446. 等差数列划分 II - 子序列

算法原理:

  💡细节: 

1.同上一题,一维dp数组无法判断是否能构成等差数列,只能知道子序列的个数,但是不能确定一个具体的子序列

2.状态转移方程:由于这里a可能有多个位置,but这里不只是看最后一个位置,而是每个位置都需要考虑,因为dp表示的是等差数列的个数,而不是最大长度

dp[i][j] +=dp[k][i]+1 (有多少个加多少个)

3.找k下标遍历优化:可以在dp之前,将<元素,下标数组>存入哈希表中

4.返回值:dp表的和(因为是个数)

5.代码注意:因为题目数据保证答案是一个 32-bit 整数,怕运算的时候越界,需要将int a改为long,同时Map第一个参数改为Long ,tmp也改为long

class Solution {
    public int numberOfArithmeticSlices(int[] nums) {
        int n = nums.length;

        int[][] dp = new int[n][n];

        Map<Long,List<Integer>> hash = new HashMap<>();
        //把<元素,下标数组>存入hash
        for(int i=0;i<n;i++) {
            long tmp = nums[i];
            if(!hash.containsKey(tmp)) {//看以前是否创建了对应的下标数组
                hash.put(tmp,new ArrayList<>());
            }
            hash.get(tmp).add(i);//将下标放入下标数组
        }

        int sum=0;
        for(int j=2;j<n;j++) {
            for(int i=1;i<j;i++) {
                long a = 2L*nums[i]-nums[j];
                if(hash.containsKey(a)) {//看第一个数a是否存在
                    for(int k:hash.get(a)) {
                        if(k<i) dp[i][j]+=dp[k][i]+1;
                        else break;//可能比i大的k有多个
                    }
                }
                sum+=dp[i][j];
            }
        }
        return sum;
    }
}

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

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

相关文章

手机图片恢复不求人:手动找回丢失的照片!

无论是外出旅行、聚会还是日常点滴&#xff0c;我们总是习惯用手机记录下来&#xff0c;让美好的瞬间定格在一张张照片中。然而&#xff0c;有时因为误删、清空缓存或是更换手机&#xff0c;那些珍贵的照片突然消失了。手机图片恢复有什么简单易行、容易上手的方法吗&#xff1…

Flink 高可用之StandAlone-HA模式(一)

Flink 高可用之StandAlone-HA模式 压缩包: tar -xvzf flink-1.9.1-bin-scala_2.11.tgz -C /opt && cd /opt/flink-1.9.1 集群规划: 1.集群规划 - 服务器: node1(Master Slave): JobManager TaskManager- 服务器: node2(Master Slave): JobManager TaskManager- …

【介绍下JSON,JSON是什么?】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

【三十一】springboot+easyExcel实现多文件导出压缩包

互相交流入口地址 整体目录&#xff1a; 【一】springboot整合swagger 【二】springboot整合自定义swagger 【三】springboot整合token 【四】springboot整合mybatis-plus 【五】springboot整合mybatis-plus 【六】springboot整合redis 【七】springboot整合AOP实现日志操作 【…

用AI绘画制作虚拟网红!9个月涨粉30万!超强变现案例分享

大家好&#xff0c;我是向阳。 2023年是AI爆发的一年&#xff0c;AI的飞速发展&#xff0c;让创造AI虚拟人变得简单&#xff0c;于是有人发明一种玩法&#xff1a;AI虚拟网红&#xff0c;模拟真人的外观和生活方式&#xff0c;吸引流量和商家关注。 其中fit_aitana就是一个典型…

设备接入物联网平台必须掌握的关键信息——青创智通

工业物联网解决方案-工业IOT-青创智通 设备接入物联网平台需要掌握的信息相当丰富且复杂&#xff0c;这涉及到多个层面&#xff0c;包括技术细节、平台选择、安全性考虑以及后期管理与维护等。以下将详细阐述设备接入物联网平台所需掌握的关键信息。 首先&#xff0c;我们需要…

充电桩战火重燃,特来电、星星充电上演“龙虎斗”

配图来自Canva可画 小米Su7真的太火了&#xff0c;上市40天锁单量超过10万供不应求&#xff0c;给新能源汽车行业带来了新的活力&#xff0c;也促进了充电桩行业的发展。 据中国汽车工业协会数据&#xff0c;4月份新能源汽车产销分别完成87万辆和85万辆&#xff0c;同比分别增…

ROS 手眼标定 realsense435i+ur5e

手眼标定的原理 基坐标系&#xff08;base_tree&#xff09;和相机&#xff08;camera_tree&#xff09;两个坐标系属于不同的tree&#xff0c;通过将标签贴到手上&#xff0c;相机识别出标签的position和orention&#xff0c;并通过easy_handeye标定包得到tool0(机械手)&…

企业数据治理:挑战与机遇并存的道路

在数字化浪潮席卷全球的今天&#xff0c;数据已经成为企业最宝贵的资产之一。然而&#xff0c;如何有效地管理和利用这些数据&#xff0c;确保数据的准确性、可靠性和安全性&#xff0c;成为了摆在企业面前的一大难题。数据治理&#xff0c;作为这一难题的解决方案&#xff0c;…

03-行为型模式(共10种)

上一篇: 02-结构型设计模式(共7种) 1. Strategy(策略模式) 策略模式是一种行为型设计模式&#xff0c;它定义了一系列算法&#xff0c;将每个算法封装到独立的类中&#xff0c;并使它们可以互相替换。这样可以使算法的变化独立于使用算法的客户端。 在 C 中&#xff0c;策略模式…

数据结构复习指导之图的遍历

文章目录 图的遍历 考纲内容 复习提示 1.广度优先搜索 1.1BFS算法的性能分析 1.2BFS算法求解单源最短路径问题 1.3广度优先生成树 2.深度优先搜索 2.1DFS算法的性能分析 2.2深度优先的生成树和生成森林 3.图的遍历与图的连通性 4.知识回顾 图的遍历 考纲内容 &…

Signal 即将成为JavaScript的一部分

什么是响应性&#xff1f; 在过去的几年中&#xff0c;响应性成为了所有现代前端框架以及React库的核心。 对于不熟悉前端开发的人来说&#xff0c;起初这可能是一个令人困惑的概念&#xff0c;因为它改变了常规的、自上而下的、从调用者到被调用者的顺序工作流。 在响应性范…

GIT基础02 多机器协作等命令

前言 首先我们知道git给我们提供了分支管理的功能 我们一般使用master分支作为线上环境,master分支一般是一个稳定的分支 我们通常是会创建一个其他分支进行开发,这样不会影响线上的机器运行 如果没有git提供这样的分支功能,就无法做到这一套了 指令学习 假设软件出现问题咋办…

得物质量管理体系的建设与应用

一、背景 质量保障是一门基于软件测试的系统化工程&#xff0c;遵循渐进式的发展规律。通过因地制宜地制定落地策略&#xff0c;设计场景方案&#xff0c;获取试验结果&#xff0c;并加以循环往复。最终&#xff0c;在每一位得物测试工程师的共同努力下&#xff0c;积累出一套…

Moe 混合多专家模型 原理 + 大模型的有性繁殖

Moe 混合多专家模型 原理 大模型的有性繁殖 MoE 介绍标准 Transformer 编码器MoE Transformer 编码器专家网络层 大模型的有性繁殖mergekit 合并 多个专家模型 的方式1. SLERP&#xff08;球面线性插值&#xff09;2. TIES3. DARE4. Passthrough5. Linear mergekit 合并 多个专…

vue3中实现简繁体转换

由于项目在大陆和台湾同胞同步使用&#xff0c;因此需要实现中文的简繁体转换&#xff0c;实现输入简体&#xff0c;能搜索出简体和繁体的相关内容&#xff0c;输入繁体&#xff0c;也能搜索出简繁体相关内容。忽略简繁体&#xff0c;扩大搜索范围。 引入插件&#xff1a; np…

一休:一款专业的休息提醒软件

对于长期使用电子产品的人来说&#xff0c;保护眼睛至关重要&#xff0c;不论是工作还是学习&#xff0c;适当的休息都是必要的&#xff0c;保护视力要牢记20-20-20法则&#xff0c;眼科医生陶勇也科普过&#xff1a; 使用电脑工作和学习时&#xff0c;容易会忘记时间&#x…

在面对各种问题时,我们应该如何进行数据分析

python数据分析汇总 前言一、对比分析概念特征类型案例Matplotlib的颜色字母对照表解决遇到未知函数 二、相关性分析概念类型案例一案例二 三、时间序列分析概念类型案例 四、回归分析概念类型案例一案例二案例三 五、决策树概念计算过程案例 六、主成分分析概念计算过程案例 七…

【手势识别-UILongPressGestureRecognizer长按 Objective-C语言】

一、我们来说这个长按啊, 1.长按这个手势,也是,步骤都是一样的,首先,也是这三大步啊, 1)创建手势对象 2)对某一个view添加手势 3)实现手势的方法 首先,也是三大步, 1)创建手势对象:首先,你要告诉我,你要使用哪一个手势,我要使用一个叫做UILongPressGesture…

[牛客网]——C语言刷题day4

答案&#xff1a;B 解析&#xff1a; a是数组首元素的地址,a1的步长是int&#xff0c;所以是2 &a是数组的首地址&#xff0c;&a1步长是int[5] ptr是int类型的指针&#xff0c;指向a数组的尾后位置&#xff0c;ptr-1的步长是int,所以是a数组的最后一个元素5 答案&am…