题目描述
如果序列 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
<
i<
i<j$)。如果我们能找到一个
k
k
k(
k
>
i
k>i
k>i且
k
>
j
k>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的力量依旧一无所知