为什么Python不会做很多递归呢?

时间:2015-01-26 14:40:48

标签: python recursion fibonacci

我正在处理项目欧拉问题,而我是第二号。问题是:

Fibonacci序列中的每个新术语都是通过添加前两个术语生成的。从1和2开始,前10个术语将是: 1,2,3,5,8,13,21,34,55,89 ...... 通过考虑Fibonacci序列中的值不超过四百万的项,找到偶数项的总和。

我试图在python中解决这个问题。我认为我有正确的代码,但由于某种原因当我运行它时,n大于或等于27,它将等待一分钟然后返回0.但是,对于26或更低的任何东西,它运行正常。这是我的代码:

def fib_seq(n):
    if n == 0:
        return n
    elif n == 1:
        return n
    else:
        return fib_seq(n-1) + fib_seq(n-2)

def get_fib_sum(n):
    x = n
    sum = 0
    for i in range(n):
        if fib_seq(x) > 4000000:
            pass
        elif fib_seq(x) % 2 == 0:
            pass
        else:
            sum += fib_seq(x)
            x = i
    return sum

print get_fib_sum(27)

无论如何要解决这个问题或至少让它起作用?如果它有所作为,我使用的是Wing IDE 101学生版。

4 个答案:

答案 0 :(得分:3)

在您的循环中,您使用的是fib_seq(x),它应该是fib_seq(i)

此外,如果您想减少时间,可以使用记忆技术

def fib_seq(n):
    if n == 0:
        return n
    elif n == 1:
        return n
    else:
        return fib_seq(n-1) + fib_seq(n-2)

def memoize(fn, arg):
 memo = {}
 if arg not in memo:
  memo[arg] = fn(arg)
  return memo[arg]


fibm = memoize(fib_seq,27)
print fibm

答案 1 :(得分:3)

为什么使用递归?你的代码会反复重复计算整个斐波纳西序列...代码只需要偶数项的总和。递归需要 NO 。在伪代码中:

t1 = 1
t2 = 2;
sum = 2;
do {
   t3 = t1 + t2;
   if (t3 is even) {
      sum += t3;
   }
   t1 = t2;
   t2 = t3;
} while (t2 <= 4000000)

答案 2 :(得分:3)

Fibonacci序列经常被用作如何编写递归代码的一个例子,这很荒谬,因为它有一个非常直接的迭代解决方案:

def fib(n):
    if n < 2:
        return n
    else:
        a, b = 1, 1
        for _ in range(2, n):    # O(n)
            a, b = b, a+b
        return b

不太明显的是它还有一个矩阵表示,

F = [[0, 1]]      # initial state

T = [[0, 1],      # transition matrix
     [1, 1]]

fib(n) = (F * T**n)[0][0]

非常有用,因为可以T**n步骤计算O(log(n))

(另外,转换矩阵的对数的特征向量导致解析解,

phi = (1 + 5**0.5) / 2     # golden ratio
fib(n) = round(phi**n / 5**0.5, 0)

但那不是我要去的地方。)

查看以奇数或偶数产生的术语,您会看到

n:        0,    1,    2,    3,    4,    5,    6,    7,    8, ... 
f(n):     0,    1,    1,    2,    3,    5,    8,   13,   21, ...
e/o:   even,  odd,  odd, even,  odd,  odd, even,  odd,  odd, ...

所以你需要的是fib(0) + fib(3) + fib(6) + ...,而计算T**3会为你提供直接从一个学期到另一个学期所需的系数。

其余部分留给读者练习;-)

答案 3 :(得分:0)

它做了很多递归,这就是为什么它花了这么长时间。

get_fib_sum()将在循环中评估fib_seq(27),这会进行大量递归并需要一段时间。由于fib_seq(27)的结果大于4000000,因此它将永远不会向sum添加任何内容,最后返回0。