在小于O(n)的范围内找到小于给定数字的斐波那契和

时间:2017-08-03 15:07:28

标签: python algorithm lambda functional-programming

我正在努力研究一个问题,解决方案的一部分是找到小于输入数的finbonacci数的总和。现在输入数字的上限是10 ** 9。我已经将问题简化为以下O(n)解决方案,我想知道是否有更有效的解决方案。

b=[1, 2, 4, 7, 12, 20, 33, 54, 88, 143, 232, 376, 609, 986, 1596, 2583, 4180, 6764, 
10945, 17710, 28656, 46367, 75024, 121392, 196417, 317810, 514228, 832039, 
1346268, 2178308, 3524577, 5702886, 9227464, 14930351, 24157816, 
39088168, 63245985, 102334154, 165580140, 267914295, 433494436, 701408732, 1134903169, 1836311902]

def test_lambda(a):
    list_numbers= filter(lambda x: x<=a, b)
    return len(list_numbers)

如您所见,我将列表b的值与给定输入进行比较,并返回小于给定数字的元素。

b是该指数的斐波那契数之和列表,因此第1个数为1,总和为1,第2个为1,总和为2,第3个为4个总数...

2 个答案:

答案 0 :(得分:1)

您只需使用二进制搜索(例如使用bisect_right功能):

from bisect import bisect_right

def test_lambda(a):
    return bisect_right(list_numbers,a)

或者如果您希望总和小于输入数字,您可以使用:

from bisect import bisect_right

def less_than(a):
    return a[bisect_right(list_numbers,a)-1]

这是有效的,因为列表是预先计算的并且是严格递增的。这意味着它是一个有序列表。二进制搜索在 O(log n)中工作,因此可以有效地进行搜索。此外,我会将0添加到列表中(位于第一个位置),以便解析0作为输入的查询:

from bisect import bisect_right

b=[0, 1, 2, 4, 7, 12, 20, 33, 54, 88, 143, 232, 376, 609, 986, 1596, 2583, 
   4180, 6764, 10945, 17710, 28656, 46367, 75024, 121392, 196417, 317810,
   514228, 832039, 1346268, 2178308, 3524577, 5702886, 9227464, 14930351,
   24157816, 39088168, 63245985, 102334154, 165580140, 267914295, 433494436,
   701408732, 1134903169, 1836311902
  ]

def less_than(a):
    return a[bisect_right(list_numbers,a)-1]

答案 1 :(得分:0)

这可以使用矩阵求幂在O(logn)* O(logn)中完成,请参考下面的链接
https://math.stackexchange.com/questions/1102452/modulus-of-sum-of-sequence-of-fibonacci-numbers
如果你没有足够的内存存储所有10 ^ 9总和你可以使用这个O(logn)计算第i个总和,如果你想要总和小于等于给定输入你可以只是二进制搜索我