JAVA程序设计:最长的斐波那契子序列的长度(LeetCode:873)

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

n >= 3
对于所有 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] 。
 

提示:

3 <= A.length <= 1000
1 <= A[0] < A[1] < ... < A[A.length - 1] <= 10^9
(对于以 Java,C,C++,以及 C# 的提交,时间限制被减少了 50%)

方法一:倘若我们已知斐波那契数列的前两项,则第三项唯一确定(a[i-1]+a[i-2]),并且我们知道在数的大小只有[0,10^9]范围内,斐波那契数列不会超过45项,因此我们可以暴力起始的前两项,之后通过set查找是否存在下一项。

class Solution {
    public int lenLongestFibSubseq(int[] A) {
    	
    	if(A.length<3) return 0;
    	
    	int ans=0;
    	int n=A.length;
    	Set<Integer> st=new HashSet<>();
    	
    	for(int x : A) st.add(x);
    	
    	for(int i=0;i<n;i++)
    		for(int j=i+1;j<n;j++) {
    			int x=A[j],y=A[i]+A[j];
    			int len=2;
    			while(st.contains(y)) {
    				int tmp=y;
    				y+=x;
    				x=tmp;
    				ans=Math.max(ans, ++len);
    			}
    		}
    	
    	return ans<3?0:ans;
    }
}

方法二:动态规划。

扫描二维码关注公众号,回复: 11154617 查看本文章

我们设dp[i,j]表示当前位为i上一位为j时的最长长度,则若a[i]+a[j]=a[k],dp[j,k]=dp[i,j]+1(i<j<k)。

class Solution {
    public int lenLongestFibSubseq(int[] A) {
    	
    	if(A.length<3) return 0;
    	
    	int ans=0;
    	int n=A.length;
    	Map<Integer,Integer> dp=new HashMap<>();
    	Map<Integer,Integer> index=new HashMap<>();
    	
    	for(int i=0;i<n;i++)
    		index.put(A[i], i);
    	
    	for(int k=0;k<n;k++)
    		for(int j=0;j<k;j++) {
    			int i=index.getOrDefault(A[k]-A[j], -1);
    			if(i>=0 && i<j) {
    				int val=dp.getOrDefault(i*n+j, 2)+1;
    				dp.put(j*n+k, val);
    				ans=Math.max(ans, val);
    			}
    		}
    	
    	return ans<3?0:ans;
    }
}
原创文章 1111 获赞 194 访问量 25万+

猜你喜欢

转载自blog.csdn.net/haut_ykc/article/details/105788183