67,628
社区成员




题目:
如果序列 X_1, X_2, ..., X_n 满足下列条件,就说它是 斐波那契式 的:
n >= 3
对于所有 i + 2 <= n,都有 X_i + X_{i+1} = X_{i+2}
给定一个严格递增的正整数数组形成序列 arr ,找到 arr 中最长的斐波那契式的子序列的长度。如果一个不存在,返回 0 。
(回想一下,子序列是从原序列 arr 中派生出来的,它从 arr 中删掉任意数量的元素(也可以不删),而不改变其余元素的顺序。例如, [3, 5, 8] 是 [3, 4, 5, 6, 7, 8] 的一个子序列)
示例1:
输入: arr = [1,2,3,4,5,6,7,8]
输出: 5
解释: 最长的斐波那契式子序列为 [1,2,3,5,8] 。
示例1:
输入: arr = [1,3,7,11,12,14,18]
输出: 3
解释: 最长的斐波那契式子序列有 [1,11,12]、[3,11,14] 以及 [7,11,18] 。
提示:
3 <= arr.length <= 1000
1 <= arr[i] < arr[i + 1] <= 10^9
思路:
动态规划 + 哈希表
下标i j k
成立,我们将j k
存入dp
里,值为i j
为结尾的序列前面的个数 +1
总结:如果(i, j)
和(j, k)
是连通的,dp[j, k] = dp[i, j] + 1
。
例arr = [1,2,3,4,5,6,7,8]
,子序列为[1,2,3,5,8]
此时j k
指向5 8
的话,dp[5,8] = dp[3, 5] + 1 = d[2,3] + 1 + 1 = dp[1,2] + 1 + 1 + 1 = 3
class Solution {
public:
int lenLongestFibSubseq(vector<int>& arr) {
int n = arr.size();
unordered_map<int, int> index;
for(int i = 0; i < n; i++) {
index[arr[i]] = i;
}
// 保存dp[j*n+k],值表示j k 序列前面的个数
unordered_map<int, int> dp;
int ans = 0;
for(int k = 0; k < n; k++) {
for(int j = 0; j < k; j++) {
// i存在并且i < j,防止i j取两边,保证 i < j
if(index.count(arr[k] - arr[j]) && index[arr[k] - arr[j]] < j) {
int i = index[arr[k] - arr[j]];
dp[j * n + k] = dp[i * n + j] + 1;
// j k前面个数加上 j k两个数
ans = max(ans, dp[j * n + k] + 2);
}
}
}
return ans;
}
};