A sequence X_1, X_2, …, X_n is fibonacci-like if:
n >= 3
X_i + X_{i+1} = X_{i+2} for all i + 2 <= n
Given a strictly increasing array A of positive integers forming a sequence, find the length of the longest fibonacci-like subsequence of A. If one does not exist, return 0.
(Recall that a subsequence is derived from another sequence A by deleting any number of elements (including none) from A, without changing the order of the remaining elements. For example, [3, 5, 8] is a subsequence of [3, 4, 5, 6, 7, 8].)
此题的最优解法是dp, dp的题目还真不是那么好做的。。
i j k
3, 4, 5, 6, 7, 8
外层循环我们在循环这个k,
对于每个k,我们循环去找它前面的一个index j
使得a[k] - a[j] 存在 (怎么找?先把value -> index的mapping存到map里去)
找到这样一个符合要求的i, j, k, 我们会希望,当我算到k这里的时候,以i, j结尾的斐波那契序列长度是已经算出来的了,那 以j, k结尾的就+1就行了,
因为以i, j结尾的斐波那契序列,后面跟的就是k,这是同一个序列
dp[i][j] 存的就是以i, j结尾的斐波那契序列,到j为止的长度 ( i<j )
这题很容易会以为要一维的数组dp[i]来存, 以i结尾的斐波那契序列最大长度,但是只用一维你没办法推出下一个值是什么
序列结尾的两个数都定了,就知道下一个值应该是什么
public int lenLongestFibSubseq(int[] a) {
Map<Integer, Integer> map = new HashMap();
for(int i = 0; i< a.length;i++) {
map.put(a[i], i);//value -> index
}
int[][] f = new int[a.length][a.length];
int ans = 2;
for(int k = 2; k < a.length; k++) {
for(int j = 1; j < k; j++) {
int i = map.getOrDefault(a[k] - a[j], -1);
if(i >= 0 && i < j) {//规定i < j < k,不然会乱
f[j][k] = (f[i][j] < 2 ? 2 : f[i][j]) + 1;
ans = Math.max(ans, f[j][k]);
}
}
}
return ans == 2? 0: ans;
}