当前位置: 首页 > news >正文

《剑指 Offer》专项突破版 - 面试题 93 : 最长斐波那契数列(C++ 实现)

题目链接:最长斐波那契数列

题目

输入一个没有重复数字的单调递增的数组,数组中至少有 3 个数字,请问数组中最长的斐波那契数列的长度是多少?例如,如果输入的数组是 [1, 2, 3, 4, 5, 6, 7, 8],由于其中最长的斐波那契数列是 1、2、3、5、8,因此输出 5。

分析

所谓斐波那契数列,是指数列中从第三个数字开始每个数字都等于前面两个数字之和,如数列 1、2、3、5、8、13 就是一个斐波那契数列。

可以从左至右每次从输入的数组中取出一个数字,使之和前面的若干数字组成斐波那契数列。一个数字可能和前面不同的数字组成不同的斐波那契数列。例如,输入数组 [1, 2, 3, 4, 5, 6, 7, 8],假设我们处理到数字 6,数字 6 就可以和前面的数字组成两个斐波那契数列,分别是 1、5、6 和 2、4、6。也就是说,每处理到一个数字时可能面临若干选择,需要从这些选择中找出最长的斐波那契数列。解决一个问题需要多个步骤,每一步面临若干选择,这个题目看起来适合运用回溯法。但由于这个问题没有要求列出所有的斐波那契数列,而是找出最长斐波那契数列的长度,也就是求最优解,因此可以用动态规划来解决这个问题。

分析确定状态转移方程

应用动态规划的关键在于找出状态转移方程。将数组记为 A,A[i] 表示数组中下标为 i 的数字。对于每个 j(0 <= j < i),A[j] 都有可能是在某个斐波那契数列中 A[i] 前面的一个数字。如果存在一个 k(0 <= k < j)满足 A[k] + A[j] = A[i],那么这 3 个数字就组成了一个斐波那契数列。这个以 A[i] 为结尾、前一个数字是 A[j] 的斐波那契数列是在以 A[j] 为结尾、前一个数字是 A[k] 的序列的基础上增加一个数字 A[i],因此前者的长度是在后者的长度的基础上加 1

例如,在数组 A = [1, 2, 3, 4, 5, 6, 7, 8] 中,A[7] 等于 8。数字 8 既可以在 1、2、3、5(结尾数字为 A[4])的基础上形成更长的斐波那契数列,也可以和数字 6(A[5])一起形成斐波那契数列 2、6、8,还可以和数字 7(A[6])一起组成斐波那契数列 1、7、8。虽然序列 2、6 和 1、7 本身都不是斐波那契数列,但在后面添加数字 8 之后就变成斐波那契数列

由于以 A[i] 为结尾的斐波那契数列的长度依赖于它前面的数字 A[j],不同的 A[j] 能和 A[i] 形成不同的斐波那契数列,它们的长度也可能不同。因此,状态转移方程有两个参数 i 和 j,f(i, j) 表示以 A[i] 为最后一个数字、A[j] 为倒数第 2 个数字的斐波那契数列的长度。如果数组中存在一个数字 k,使 A[i] = A[j] + A[k](0 <= k < j < i),那么 f(i, j) = f(j, k) + 1,即在以 A[j] 为最后一个数字、A[k] 为倒数第 2 个数字的斐波那契数列的基础上增加一个数字 A[i],形成更长的一个数列。f(i, j) 的值可能是 2,此时虽然 A[i] 和 A[j] 这两个数字现在还不能形成一个有效的斐波那契数列,但可能会在之后增加一个新的数字使之形成长度为 3 甚至更长的斐波那契数列

根据状态转移方程写代码

由于状态转移方程有两个参数 i 和 j,因此需要一个二维数组来缓存 f(i, j) 的计算结果。i 对应二维数组的行号,j 对应二维数组的列号。由于 i 大于 j,因此实际上只用到了二维数组的左下角部分。如果数组的长度是 n,那么 i 的取值范围为 1 ~ n - 1,而 j 的取值范围为 0 ~ n - 2

下表记录了计算数组 [1, 2, 3, 4, 5, 6, 7, 8] 中最长斐波那契数列的长度的过程。

代码实现

class Solution {
public:int lenLongestFibSubseq(vector<int>& arr) {unordered_map<int, int> numToIndex;numToIndex[arr[0]] = 0;
​int n = arr.size();vector<vector<int>> dp(n, vector<int>(n - 1));int result = 0;for (int i = 1; i < n; ++i){for (int j = 0; j < i; ++j){int target = arr[i] - arr[j];if (numToIndex.count(target) && numToIndex[target] < j){int k = numToIndex[target];dp[i][j] = dp[j][k] + 1;result = max(result, dp[i][j]);}else{dp[i][j] = 2;}}numToIndex[arr[i]] = i;}return result;}
};

相关文章:

《剑指 Offer》专项突破版 - 面试题 93 : 最长斐波那契数列(C++ 实现)

题目链接&#xff1a;最长斐波那契数列 题目&#xff1a; 输入一个没有重复数字的单调递增的数组&#xff0c;数组中至少有 3 个数字&#xff0c;请问数组中最长的斐波那契数列的长度是多少&#xff1f;例如&#xff0c;如果输入的数组是 [1, 2, 3, 4, 5, 6, 7, 8]&#xff0…...

代码随想录算法训练营第五十五天|583. 两个字符串的删除操作、72. 编辑距离

583. 两个字符串的删除操作 刷题https://leetcode.cn/problems/delete-operation-for-two-strings/description/文章讲解https://programmercarl.com/0583.%E4%B8%A4%E4%B8%AA%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9A%84%E5%88%A0%E9%99%A4%E6%93%8D%E4%BD%9C.html视频讲解https://…...

StringRedisTemplate Autowired注入为空解决

如下注入方式报空指针异常&#xff1a; java.lang.NullPointerException: null Autowiredprivate StringRedisTemplate redisTemplate; 解决办法&#xff1a;查看该类上有没有加注解&#xff0c;如Component等&#xff0c;没加的话加上。 还有一种是在工具类中使用&#xff0c;…...

c语言:文件操作

1. 为什么使⽤⽂件&#xff1f; 如果没有⽂件&#xff0c;我们写的程序的数据是存储在电脑的内存中&#xff0c;如果程序退出&#xff0c;内存回收&#xff0c;数据就丢失 了&#xff0c;等再次运⾏程序&#xff0c;是看不到上次程序的数据的&#xff0c;如果要将数据进⾏持久…...

C#事件实例详解

一、什么是事件&#xff1f; 在C#中,事件(event)是一种特殊的类成员,它允许类或对象通知其他类或对象发生了某些事情。 从语法上看,事件的声明类似于字段,但它们在功能和行为上有一些重要的区别。 从技术角度来说,事件实际上是一个封装了事件订阅和取消订阅功能的委托字段。…...

零基础机器学习(3)之机器学习的一般过程

文章目录 一、机器学习一般过程1.数据获取2.特征提取3.数据预处理①去除唯一属性②缺失值处理A. 均值插补法B. 同类均值插补法 ③重复值处理④异常值⑤数据定量化 4.数据标准化①min-max标准化&#xff08;归一化&#xff09;②z-score标准化&#xff08;规范化&#xff09; 5.…...

用java做一个双色球彩票系统

代码如下&#xff1a; import java.util.Random; public class HelloWorld{public static void main(String[] args){//1、生成中奖号码 int[] arrcreateNumber();for (int i 0;i<arr.length;i) {System.out.print(arr[i]" ");}}public static int[] createNu…...

某对象存储元数据集群改造流水账

软件产品&#xff1a;某厂商提供的不便具名的对象存储产品&#xff0c;核心底层技术源自HDFS和Amazon S3&#xff0c;元数据集群采用了基于MongoDB的NOSQL数据库产品和MySQL数据库产品相结合。 该产品的元数据逻辑示意图如下&#xff1a; 业务集群现状&#xff1a;当前第3期建…...

前端理论总结(js)——filter、foearch、for in 、for of 、for的区别以及返回值

Filter&#xff1a; 用途&#xff1a;用于筛选数组中符合条件的元素&#xff0c;返回一个新数组。 返回值&#xff1a;返回一个新数组&#xff0c;包含经过筛选的元素。 Foreach&#xff1a; 用途&#xff1a;遍历数组中的每个元素&#xff0c;执行回调函数。 返回值&#x…...

【JavaEE初阶系列】——多线程案例一——单例模式 (“饿汉模式“和“懒汉模式“以及解决线程安全问题)

目录 &#x1f6a9;单例模式 &#x1f388;饿汉模式 &#x1f388;懒汉模式 ❗线程安全问题 &#x1f4dd;加锁 &#x1f4dd;执行效率提高 &#x1f4dd;指令重排序 &#x1f36d;总结 单例模式&#xff0c;非常经典的设计模式&#xff0c;也是一个重要的学科&#x…...

革新水库大坝监测:传统软件与云平台之比较

在水库大坝的监测管理领域&#xff0c;传统监测软件虽然曾发挥了重要作用&#xff0c;但在多方面显示出了其局限性。传统解决方案通常伴随着高昂的运维成本&#xff0c;需要大量的硬件支持和人员维护&#xff0c;且软件整合和升级困难&#xff0c;限制了其灵活性和扩展性。 点击…...

C++模版(基础)

目录 C泛型编程思想 C模版 模版介绍 模版使用 函数模版 函数模版基础语法 函数模版原理 函数模版实例化 模版参数匹配规则 类模版 类模版基础语法 C泛型编程思想 泛型编程&#xff1a;编写与类型无关的通用代码&#xff0c;是代码复用的一种手段。 模板是泛型编程…...

MySQL驱动Add Batch优化实现

MySQL 驱动 Add Batch 优化实现 MySQL 驱动会在 JDBC URL 添加 rewriteBatchedStatements 参数时&#xff0c;对 batch 操作进行优化。本文测试各种参数组合的行为&#xff0c;并结合驱动代码简单分析。 batch参数组合行为 useServerPrepStmts 参数 PreparedStatement psmt…...

手撕算法-数组中的第K个最大元素

描述 分析 使用小根堆&#xff0c;堆元素控制在k个&#xff0c;遍历数组构建堆&#xff0c;最后堆顶就是第K个最大的元素。 代码 class Solution {public int findKthLargest(int[] nums, int k) {// 小根堆PriorityQueue<Integer> queue new PriorityQueue<>…...

【vue】computed和watch的区别和应用场景

Computed 和 Watch 是 Vue.js 中用于监视数据变化的两个不同特性&#xff0c;它们各自有不同的应用场景和功能。 Computed&#xff1a; 计算属性&#xff08;Computed properties&#xff09;用于声明基于其他数据属性的计算值。它具有缓存功能&#xff0c;只有在依赖的数…...

ARM.day8

1.自己设置温度湿度阈值&#xff0c;当温度过高时&#xff0c;打开风扇&#xff0c;蜂鸣器报警 2.当湿度比较高时&#xff0c;打开LED1灯&#xff0c;蜂鸣器报警 main.c #include "si7006.h" #include "CH1.h" #include "led.h" // 延时函数in…...

SpringCloud Gateway工作流程

Spring Cloud Gateway的工作流程 具体的流程&#xff1a; 用户发送请求到网关 请求断言&#xff0c;用户请求到达网关后&#xff0c;由Gateway Handler Mapping&#xff08;网关处理器映射&#xff09;进行Predicates&#xff08;断言&#xff09;&#xff0c;看一下哪一个符合…...

西井科技与安通控股签署战略合作协议 共创大物流全新生态

2024年3月21日&#xff0c;西井科技与安通控股在“上海硅巷”新象限空间正式签署战略合作框架协议。双方基于此前在集装箱物流的成功实践与资源优势&#xff0c;积极拓展在AI数字化产品、新能源自动驾驶解决方案和多场景应用&#xff0c;以及绿色物流链等领域的深度探索、强强联…...

CCCorelib 点云RANSAC拟合球体(CloudCompare内置算法库)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 RANSAC是一种随机参数估计算法。RANSAC从样本中随机抽选出一个样本子集,使用最小方差估计算法对这个子集计算模型参数,然后计算所有样本与该模型的偏差,再使用一个预先设定好的阈值与偏差比较,当偏差小于阈值时…...

map china not exists. the geojson of the map must be provided.

map china not exists. the geojson of the map must be provided. 场景&#xff1a;引入echarts地图报错map china not exists. the geojson of the map must be provided. 原因&#xff1a; echarts版本过高&#xff0c;ECharts 之前提供下载的矢量地图数据来自第三方&…...

全民养虾潮背后:智能体产业的产业化困局

2026年3月&#xff0c;如果你在科技园区看到有人抱着电脑排长队&#xff0c;或者听到“养虾了吗”的问候&#xff0c;不必感到奇怪。这只“虾”正是开源AI智能体——OpenClaw。从社交平台刷屏的“养龙虾”攻略到GitHub星标数突破27万&#xff0c;超越Linux登顶全球开源项目榜首…...

Starry Night Art Gallery效果展示:黄金渐变按钮交互+实时生成反馈

Starry Night Art Gallery效果展示&#xff1a;黄金渐变按钮交互实时生成反馈 1. 沉浸式艺术体验&#xff1a;当AI遇见文艺复兴 想象一下&#xff0c;你走进的不是一个冰冷的AI工具界面&#xff0c;而是一座数字艺术殿堂。四周是深邃的墨蓝色背景&#xff0c;如同梵高笔下的夜…...

行波管TWT聚焦系统硬核拆解:PPM vs PCM 核心区别、原理对比与工程选型全指南

对于行波管&#xff08;TWT&#xff09;研发工程师、射频微波专业学生、雷达 / 通信系统硬件从业者而言&#xff0c;电子注聚焦系统是决定器件生死的核心模块—— 它直接决定了电子注的流通率、注波互作用效率&#xff0c;甚至是器件的长期可靠性。在永磁聚焦方案中&#xff0c…...

使用ZLMRTCClient.j实现webRtc流播放

1. 核心播放器组件封装 (WebRTCPlayer.vue)为了在项目中复用播放逻辑&#xff0c;我们首先封装一个 WebRTCPlayer 组件。该组件主要负责&#xff1a;初始化播放器实例&#xff1a;配置 ZLMRTCClient.Endpoint。处理自动播放&#xff1a;解决浏览器禁止带音频自动播放的问题。生…...

别再只画可达空间了!宇树Z1机械臂‘死角’排查与灵活工作空间优化实战

宇树Z1机械臂死角排查与灵活工作空间优化实战指南 当宇树Z1机械臂在自动化产线上执行抓取任务时&#xff0c;工程师们常会遇到一个令人头疼的现象——某些看似可达的位姿却无法实现预期动作。这背后隐藏的往往是机械臂工作空间中的"死角"问题&#xff0c;即那些虽然理…...

别再手动改请求头了!用BurpSuite插件5分钟搞定自动化添加(附完整Java代码)

解放双手&#xff1a;用BurpSuite插件实现HTTP请求头自动化管理 每次安全测试时&#xff0c;你是否也厌倦了反复点击"拦截"按钮、手动添加X-Debug-Header或修改User-Agent&#xff1f;作为一名长期与BurpSuite打交道的安全工程师&#xff0c;我深知这种重复性操作不仅…...

告别手写CRUD:用IDEA插件实现数据库到Java代码的智能生成

1. 为什么我们需要告别手写CRUD&#xff1f; 作为一名有多年开发经验的程序员&#xff0c;我深知手写CRUD代码的痛苦。每次新建一个表&#xff0c;就要重复编写几乎相同的实体类、Mapper接口和XML文件。这种重复劳动不仅枯燥乏味&#xff0c;还容易出错。记得有一次我因为手误把…...

AI赋能.NET开发:让快马平台智能生成Redis缓存与消息队列集成代码

最近在做一个电商系统的订单模块&#xff0c;发现缓存和消息队列这两个组件几乎是标配。但每次从零开始集成Redis和RabbitMQ都要查半天文档&#xff0c;配置各种连接字符串&#xff0c;写一堆样板代码。直到尝试用InsCode(快马)平台的AI辅助功能&#xff0c;才发现原来这些重复…...

[语音转文字工具] AsrTools:让音频转写效率提升300%的开源解决方案

[语音转文字工具] AsrTools&#xff1a;让音频转写效率提升300%的开源解决方案 【免费下载链接】AsrTools ✨ AsrTools: Smart Voice-to-Text Tool | Efficient Batch Processing | User-Friendly Interface | No GPU Required | Supports SRT/TXT Output | Turn your audio in…...

PySide6多线程避坑指南:你的‘暂停’和‘停止’真的安全吗?

PySide6多线程避坑指南&#xff1a;你的‘暂停’和‘停止’真的安全吗&#xff1f; 在PySide6的多线程开发中&#xff0c;暂停和停止线程看似简单的操作背后&#xff0c;隐藏着许多开发者容易忽视的陷阱。本文将深入剖析这些潜在问题&#xff0c;并提供经过实战验证的安全解决方…...