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

题目描述

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

  • $n>2
  • 对于所有 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] 。

解题思路

像这种类似的题目是有套路的,类似于我之前刷过的一个题,中等·AlvinZH的序列问题,这个题目是求等差序列的个数,我们可以借鉴这个题的解题方法,首先定义状态 d p ( i , j ) dp(i,j) dp(i,j),表示以 A [ i ] A[i] A[i] A [ j ] A[j] A[j]为结尾的斐波那契序列的长度(这里假设 i &lt; i&lt; i<j$)。如果我们能找到一个 k k k( k &gt; i k&gt;i k>i k &gt; j k&gt;j k>j)使得 A [ k ] = A [ i ] + A [ j ] A[k]=A[i]+A[j] A[k]=A[i]+A[j],显然我们就得到了一个新的斐波那契序列,状态转移方程为
d p [ i ] [ j ] = d p [ j ] [ k ] + 1 dp[i][j]=dp[j][k]+1 dp[i][j]=dp[j][k]+1
那么有什么方法可以快速找到这个 k k k呢?,我们可以用一个map保存每个 A A A中元素的位置,这样就可以常数时间内找到这个位置


AC代码

class Solution {
public:
    int lenLongestFibSubseq(vector<int>& A) {
	int len = A.size();
	vector<vector<int>>dp(len, vector<int>(len, 0));
	map<int, int>M;
	for (int i = 0; i < len; i++)
		M[A[i]] = i;
	int re = 0;
	for (int i = len - 1; i >= 0; i--) {
		for (int j = i + 1; j < len; j++) {
			dp[i][j] = 2;//默认为2
			int tmp = A[i] + A[j];
			if (M.count(tmp)) {
				dp[i][j] = dp[j][M[tmp]] + 1;
				if (dp[i][j] > re) re = dp[i][j];
			}
		}
	}
	return re;
}
};

小结

我对dp的力量依旧一无所知

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值