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

一、最长定差子序列

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;
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

springboot3.0+继续使用springboot2.0配置会显示 `无法自动装配,找不到对应的Bean`解决方法

在 Spring Boot 3.0 中&#xff0c;Spring 团队对自动配置机制进行了重大变更&#xff0c;特别是 spring.factories 文件。spring.factories 文件已被 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件所取代。在springboot3.0继续使用…

Danfoss丹佛斯S90泵比例放大器

S90R042、S90R055、S90R075、S90R100、S90R130、S90R180、S90R250电气排量控制变量泵比例阀放大器&#xff0c;电气排量控制为高增益控制方式&#xff1a;通过微小变化的输入电流控制信号即可推动伺服阀主阀芯至全开口位置&#xff0c;进而将最大流量的控制油引入到伺服油缸。伺…

搭建Prometheus+grafana监控系统

1. 项目目标 &#xff08;1&#xff09;熟练部署安装node_exporter &#xff08;2&#xff09;熟练部署安装prometheus &#xff08;3&#xff09;熟练部署安装grafana 2. 项目准备 2.1. 规划节点 主机名 主机IP 节点规划 prometheus-server 10.0.1.10 server prome…

光伏运维系统在光伏电站的应用

摘要&#xff1a;全球化经济社会的快速发展,加快了传统能源的消耗,导致能源日益短缺,与此同时还带来了严重的环境污染。因此,利用没有环境污染的太阳能进行光伏发电获得了社会的普遍关注。本文根据传统式光伏电站行业的发展背景及其监控系统的技术设备,给出了现代化光伏电站数据…

手机IP地址:固定还是动态?探寻背后的变化之谜

在数字化时代的今天&#xff0c;手机作为我们日常生活中必不可少的通讯工具&#xff0c;扮演着越来越重要的角色。其中&#xff0c;IP地址作为手机在网络世界中的“身份证”&#xff0c;对于手机的正常运作至关重要。然而&#xff0c;很多人对于手机IP地址的固定性存在疑问&…

电子合同怎么盖章的

数字证书盖章&#xff1a;利用个人或企业的数字证书进行盖章。数字证书作为数字身份证明&#xff0c;确保了电子签名和盖章的可信度。通过加密技术&#xff0c;确保合同内容不被篡改&#xff0c;盖章过程完成后&#xff0c;合同具有法律效力。 时间戳盖章&#xff1a;在电子合…

【AI绘画】Stable diffusion初级教程08——提示词(prompt)该如何写

今天是一篇干货&#xff0c;干的喝水的那种…… 写之前呢&#xff0c;先给大家打个比方&#xff1a;现在刚入门学习SD的相当于刚上学的小学生&#xff0c;提示词就相当于作文&#xff0c;还是英语作文&#xff0c;如果你总是抄抄抄&#xff0c;不知道作文的要点&#xff0c;语法…

实验10 协作图

一、实验目的 通过绘制活协作图&#xff0c;掌握协作图的基本原理。能对简单问题进行协作图的分析与绘制。 二、实验项目内容&#xff08;实验题目&#xff09; 考试成绩管理系统是举行成人高考、自学考试等成人高校对每个参与考试的学员成绩进行综合管理的一个系统。本系统的…

redis7基础篇2 redis的3种模式(主从,哨兵,集群)模式

一 主从复制模式 1.1 主从模式 主从模式&#xff1a; 主机可以读&#xff0c;写&#xff0c;重机只能写操作。 主机shutdown后&#xff0c;从机上位还是原地待命&#xff1a;从机不动&#xff0c;原地待命&#xff0c;数据正常使用&#xff0c;等待主机重启归来。 主机shu…

输入法变了 输入的地方由原来的一条线变成了小白方块,打完字后还会把原来的字覆盖掉

今天工作是&#xff0c;不知道不小心点了什么按键后&#xff0c;输入法变了&#xff0c; 输入的地方由原来的一条线变成了小白方块&#xff0c;打完字后还会把原来的字覆盖掉 之前都是&#xff0c;重启解决这个问题的&#xff0c;今天不想重启了&#xff0c;重启后打开工作用的…

在Linux上面部署ELK

注明&#xff1a;一下的软件需要自己准备 一、准备环境&#xff1a; 1.两台elasticsearch主机4G内存 2.两台elasticsearch配置主机名node1和node2(可以省略) #vim /etc/hostname #reboot 3. 两台elasticsearch配置hosts文件 #vim /etc/hosts 192.168.1.1 node1 192…

OpenCompass大模型离线测评

一、目录 环境配置环境测试本地模型测评 二、实现 环境配置 >>创建环境 conda create --name opencompass python3.10 pytorch torchvision pytorch-cuda -c nvidia -c pytorch -ysource activate opencompass git clone https://github.com/open-compass/opencompas…

第 8 章 机器人底盘Arduino端PID控制(自学二刷笔记)

重要参考&#xff1a; 课程链接:https://www.bilibili.com/video/BV1Ci4y1L7ZZ 讲义链接:Introduction Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程 8.4.5 底盘实现_04Arduino端PID控制 上一节最后测试时&#xff0c;电机可能会出现抖动、顿挫的现象&#xff…

力扣HOT100 - 62. 不同路径

解题思路&#xff1a; 动态规划 注意要初始化第一行和第一列的值 class Solution {public int uniquePaths(int m, int n) {int[][] dp new int[m][n];for (int i 0; i < m; i) {dp[i][0] 1;}for (int j 0; j < n; j) {dp[0][j] 1;}for (int i 1; i < m; i) {…

快手截流多功能协议引流多线程多账号使用

在市场上&#xff0c;类似的软件售价都在几千元&#xff0c;但我发现这款全新版本的软件已经更新&#xff0c;而且我只需要配合使用谷歌浏览器&#xff0c;稍微调慢一点延时&#xff0c;我就可以像专业人士一样流畅地进行操作。 评论对于我而言是一种艺术&#xff0c;而不仅仅是…

XML文件转TXT文件 yolo标签转换(代码可直接使用) 可批量转换

像这样的xml文件&#xff0c;我们可以通过代码批量转换为txt文件格式&#xff1a; 新建一个xml2txt.py文件&#xff0c; 上代码&#xff0c;直接复制粘贴 import xml.etree.ElementTree as ET import osdef convert(size, box):x_center (box[0] box[1]) / 2.0y_center (box…

Phidata:快速构建一个智能 AI 助手【附代码示例】

介绍 Phidata Phidata 是一个尖端的框架&#xff0c;专为开发具有超越传统语言模型能力的自治助手&#xff08;或称为代理&#xff09;而设计。这些 AI 助手拥有长期记忆、深入的情境理解能力以及通过函数调用执行操作的能力&#xff0c;使它们在各种应用中非常有效。项目近期…

Bootstrap Studio for Mac:打造专业级网页设计软件

对于追求高效与品质的设计师和开发者来说&#xff0c;Bootstrap Studio for Mac无疑是最佳选择。它建立在广受欢迎的Bootstrap框架之上&#xff0c;输出干净、语义化的HTML代码。同时&#xff0c;强大的CSS和SASS编辑器&#xff0c;支持自动建议和规则验证&#xff0c;让您的设…

僵尸网络的威胁值得关注

僵尸网络&#xff08;botnet&#xff09;是指一组受到恶意软件感染并遭到恶意用户控制的计算机。术语“僵尸网络”由“机器人&#xff08;bot&#xff09;”和“网络&#xff08;network&#xff09;”两个词组合而成&#xff0c;每台受感染设备被称为“机器人”。僵尸网络可用…