子串最长的斐波那契数列

思路:暴力,枚举斐波那契数列开始的两个值。若长度为2的时候,输出0

时间复杂度有点高,有没有什么优化的方式呢?

①错误思路:

把每次出现的斐波那契数列标记一下,如果下次开始的两个值都出现过,那么就结束。

1 2 3 5 8    (1和2开始,依次标记3,5,8,后续遍历2和3的时候就可以直接终止了)

错误原因:没有考虑到标记的两个数可能不是同一个斐波那契数列得到的

5 7 9 12 14 26 40

5和7标记了12,5和9标记了14。虽然12和14都标记了,但是12和14不能直接终止。

答案:12 14 26 40

②正确思路:

每次暴力取斐波那契数列的前两个值,a和b

若a+b的值出现在原序列中,继续生成下个数,直至生成的数不在原序列中终止。

剪枝:b-a若也在原序列中,那么可以直接终止,以这两个起点的斐波那契数列一定是前面的子序列。

原因:原序列是单调递增的,c=b-a的值若真的在原序列中,那么c一定在a和b的前面。那么c和a组成的斐波那契数列已经统计过了。(a和b)一定是(c和a)的子序列了。

s=input()
s=s.split(" ")
n=len(s)
dict={}
for x in s:
    dict[int(x)]=1
ans=0
for i in range(n-1):
    for j in range(i+1,n):
        a=(int)(s[i])
        b=(int)(s[j])
        if(b-a not in dict):  #没出现过
            cnt=2
            sum=a+b
            while sum in dict:
                cnt += 1
                a = b
                b = sum
                sum = a + b
        if(cnt>ans):
            ans=cnt
if(ans==2):
    print(0)
else:
    print(ans)
#5 7 9 12 14 26 40
#4

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值