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

本文介绍了一个关于寻找给定严格递增数组中最长斐波那契子序列长度的问题。当序列满足特定斐波那契条件时,称为斐波那契式。示例展示了如何解决这个问题,提示表明直接遍历算法会超时,因此采用了一种优化策略,利用二维数组存储前两个数字确定的斐波那契数列的最大长度,并从前向后遍历数组以求解。
摘要由CSDN通过智能技术生成

问题描述

如果序列  X_1, X_2, ..., X_n 满足下列条件,说它就英文的  斐波那契式 的:

  • n >= 3
  • 对于所有  i + 2 <= n,都有 X_i + X_{i+1} = X_{i+2}

定给一个严格递增的正整数数组形成序列,找到  A 中最长的那斐波契式的子序列的长度。如果一个不存在,返回0。

(回想一下,子序列的英文从原序列  A 中派生出来的,它从  A 中删掉任意数量的元素(也可以不删),而不改变其余元素的顺序。例如,  [3, 5, 8] 的英文  [3, 4, 5, 6, 7, 8] 的一个子序列)

 

示例1:

输入: [1,2,3,4,5,6,7,8]
输出: 5
解释:
最长的斐波那契式子序列为:[1,2,3,5,8] 。

示例2:

输入: [1,3,7,11,12,14,18]
输出: 3
解释:
最长的斐波那契式子序列有:
[1,11,12],[3,11,14] 以及 [7,11,18] 。

 

提示:

  • 3 <= A.length <= 1000
  • 1 <= A[0] < A[1] < ... < A[A.length - 1] <= 10^9
  • (对于以Java,C,C ++,以及C#的提交,时间限制被减少了50%)

代码实现

思路:如果直接使用遍历算法的话,时间复杂度大概是为O(n ^ 3)这个数量级,而题目要求中给出的数组甲的最大长度为1000,如果使用为O(n ^ 3)的算法,势必会超时。
考虑如何简化:斐波那契数列有一个性质,即一但前两个数字确定,整个数列即确定的故我们使用二维数组来存储这一信息,二维数组地图的两个索引分别为该斐波那契数列前两个数在甲中的索引,其对应的值为由该数列在整个序列中的最大长度
我们只要从后往前遍历整个数组,就能使用到地图中所储存的信息。

代码如下:

class Solution {
    public int lenLongestFibSubseq(int[] A) {
        int res = 0;
        // HashMap<Integer, Integer []> map = new HashMap<Integer, Integer[]>();
        int [][] map = new int [A.length][A.length];
        map[A.length- 2][A.length -1] = 2;
//        List <Integer> list = new ArrayList<>();
//        for(int i = 0 ; i < A.length ; i++){
//            list.add(A[i]);
//        }
        for(int j = A.length - 3; j >= 0; j--){
            for(int i = j + 1; i <A.length; i++){
                int three = A[j] + A[i];
                int index = findIndex(i, three , A);
                if(index != -1) {
                    map[j][i] = map[i][index] +1;
                    res = Math.max(map[j][i], res);
                }else{
                    map[j][i] = 2;
                }
            }
        }
        return res < 3 ? 0: res;
    }
    public int findIndex(int start, int target, int [] A) {
        int end = A.length -1;
        while(start <= end) {
            int mid = (start + end) / 2;
            if(A[mid] < target) {
                start = mid +1;
            }else if(A[mid] > target) {
                end = mid - 1;
            }else {
                return mid;
            }
        }
        return -1;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值