最长的斐波那契子序列的长度
题目
如果序列 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构成,那么我们怎么考虑动态方程呢?
- 取dp[x][y] (x<y)表示结尾为 arr[x], arr[y] 所组成的最长斐波那契序列
- 推出,数组如果存在一个数 arr[z] 满足 arr[x] + arr[y] ,
- 那么 dp[y][z]=max(dp[x][y]+1,dp[y][z])
- 而怎么判断这个数arr[z]是否存在,以及这个数所在数组的位置,我们可以采用hashmap
- key:arr[z] value: z
- 对于最长斐波那契序列的长度,我们只要在求出每一个dp[x][y],做比较即可
- int res = 0 ; res = max(dp[x][y],res)
代码
class Solution {
public int lenLongestFibSubseq(int[] arr) {
int len = arr.length;
if(len<3){
return 0;
}
HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
int dp[][] = new int[len][len];
int index = 0 ;
for(int x :arr){
map.put(x,index++);
}
int max = 0 ;
for(int i = 0 ; i < len ; i++){
for(int j = i+1 ; j < len; j++){
if(map.containsKey(arr[i]+arr[j])){
int x = map.get(arr[i]+arr[j]);
dp[j][x]=Math.max(dp[i][j]+1,dp[j][x]);
if(max<dp[j][x]){
max = dp[j][x];
}
}
}
}
return max==0?0:max+2;
}
}