2017-08-03 29 views
1

我想解决一个问题,部分解决方案是找到小于输入数字的finbonacci数字的总和。现在输入数字的上限是10 ** 9。我已经将问题简化为以下O(n)解决方案,我想知道是否有更高效的解决方案。找到小于给定数字的斐波那契和小于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为fibonaccis数高达该索引的总和的列表,因此第一数目为1时,总和为1时,第二是1的总和是2时,第三2之和4 ...

+0

你知道有一个小于O(n)的解决方案,或者你只是想要一个? –

+4

只需使用二进制搜索... –

+0

我不知道是否有一个小于O(n)的解决方案... – fazkan

回答

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] 
+0

bisect_right的效率是多少,我在某处读取它的log(n)... – fazkan

+0

@fazkan:它肯定是* O(log n)*用于搜索(绝对给出的元素都是不同的),作为记录在'insort_left'函数中。 –