此代码是否有更快的版本?
def perimeter(n):
a = [1, 1]
for i in range(n-1):
a.append(a[i+1]+a[i])
return 4*sum(a)
我试图在代码大战上解决一些任务,但是有一个错误:
流程已终止。完成时间超过6000毫秒
答案 0 :(得分:0)
不使用斐波那契数的总和公式(在http://math.stackexchange.com上询问),你的解决方案应该和它一样快。使用矩阵形式不应该有很多帮助,因为你必须进行取幂。
但是,您可以先使用xrange
而不是range
来避免内存分配(您使用的是python2)。而且还没有将数字存储在不断增长的数组中:
def perimeter(n):
a, b = 1, 1
s = a+b
for i in xrange(n-1):
a, b = b, a+b
s+=b
return 4*s
公式解决方案(使用斐波纳契数最多为F(j)的总和为F(j + 2)-2)将是:
def perimeter(n)
if n == 0:
return 8 # a special case where you add the two first fibonacci numbers anyway.
n = n+3
phi = (math.sqrt(5)-1)/2
return 4*int(round((phi**n - (-phi)**(-n))/math.sqrt(5)))-4
使用最后一个解决方案时要小心,因为你最终会得到舍入错误,这会让你错过Fibonacci数字。
为了解决准确性问题,我们可以使用a+b*sqrt(5)
形式的正式表达式。为简单起见,我将它们封装在一个类中:
class Golden:
def __init__(self, a, b):
self.a = a
self.b = b
def __mul__(self, other):
return Golden( self.a*other.a + 5*self.b*other.b,
self.a*other.b + self.b*other.a )
def __pow__(self, n):
if n == 1:
return self
if n % 2 == 0:
return (self * self) ** (n/2)
return self * (self * self) ** ((n-1)/2)
def __add__(self, other):
return Golden(self.a + other.a, self.b+other.b)
def __sub__(self, other):
return Golden(self.a - other.a, self.b-other.b)
def perimeter3(n):
if n == 0:
return 8
n = n+3
phi = Golden(1,1)
psi = Golden(1,-1)
fn = (phi**n - psi**n)
assert fn.a == 0
return 4*(fn.b / (2 ** n)-1)
这有一个轻微的缺点,它迭代地计算功率,但是这样做所需的步骤数不是n,而是log(n),它应该使它比第一个解决方案更具优势(中间的缺点只有在准确性使中间解决方案失败之前才有意义 - 这只适用于小的n。)
答案 1 :(得分:0)
您可以生成斐波纳契对:
def fibonacci_pairs(n):
a, b = 0, 1
for i in xrange(n):
yield a, b
a, b = b, a + b
然后:
>>> sum(b for a, b in fibonacci_pairs(10))
答案 2 :(得分:0)
你可以注意到一个数学事实。我们a0, a1, a2 ...
是斐波纳契数。您想要计算此声明:
a0 + a1 + a2 + a3 + ... + an = Sn
另一方面,a = a {n-1} + a {n-2}:
Sn = 2*a{n-1} + 2*a{n-2} + a{n-3} + ... + a1 + a0 = (2*a{n-1} + 2*a{n-2} + 2*a{n-3} + ... + 2*a1 + 2*a0) - (a{n-3} + ... + a1 + a0) = 2*S{n-1} - S{n-3}
换句话说,我们得到了一个递归语句:
Sn = 2*S{n-1} - S{n-3}
使用python我们可以编写这样的函数:
cache = {}
def S(n):
if n in cache:
return cache[n]
if n <= 2:
return n
else:
r = 2 * S(n - 1) - S(n - 3)
cache[n] = r
return r
def perimeter(n):
return 4 * S(n)
print S(1000) # it prints 113796925398360272257523782552224175572745930353730513145086634176691092536145985470146129334641866902783673042322088625863396052888690096969577173696370562180400527049497109023054114771394568040040412172632375