在python中使用词典进行动态绑定?

时间:2013-05-17 03:06:15

标签: python recursion dictionary dynamic-programming fibonacci

我知道如何递归地完成Fibonacci系列,这非常简单:

def F(n):
  if n == 1 or n == 2:
    return 1
  else:
    return k * F(n-2) + F(n - 1)

但我确实知道这是非常低效的,因为它必须一次又一次地计算相同的值。解决这个问题的方法是以某种方式存储值。假设您想要第20个值。一旦你计算了F(13)是什么,它的值可以直接存储和调用,而不是通过所有的递归级别来得到相同的答案。

字典是解决此问题的明显方法。但是,我对字典的回答不起作用。

U = {1:1, 2:1}
def F(n):
  global U
  if n in U:
    return U[n]
  else:
    U[n] = F(n - 2) + F(n - 1)

运行此代码后,只需打印U [n]。

我已多次执行逻辑,一切似乎都很好,但我一直收到这个错误:

TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'

每当我尝试一个大于3的数字时,我都不会看到None应该如何返回,但我承认我可能会错过某些导致问题的词典的细微差别。

4 个答案:

答案 0 :(得分:1)

您在return子句中缺少else语句。

def F(n):
  global U
  if n in U:
    return U[n]
  else:
    U[n] = F(n - 2) + F(n - 1)
    return U[n]

或简化:

def F(n):
  if n not in U:
    U[n] = F(n - 2) + F(n - 1)
  return U[n]

(不需要global。)

答案 1 :(得分:0)

使用可变默认值仅初始化一次的简单方法

def F(n, U={1: 1, 2: 1}):
  if n not in U:
    U[n] = F(n - 2) + F(n - 1)
  return U[n]

这样可以避免在全局命名空间中使用U

答案 2 :(得分:0)

  • n不在U中时,您还应该返回U[n]

只需:

U = {1:1, 2:1}
def F(n):
    global U
    if n in U:
        return U[n]
    else:
        U[n] = F(n - 2) + F(n - 1)
        return U[n]
  • 对于efficient
    • 如果你想做一次,你的第二种方式是牺牲空间,并且得到时间,我不知道在真正的开发环境中哪个更好。
    • 如果你想多次获得U [n],最好按U存储

因此,如果您想存储该值,可能是:

U = {1:1, 2:1}
def F(n):
    for i in range(3, n+1):
        U[i] = U[i - 2] + U[i - 1]
    return U

fb = F(10)

print fb[3]
print fb[5]
print fb[10]

答案 3 :(得分:0)

如果您需要memoization,可以使用functools.lru_cache(> = python 3.2)。它完全符合您的要求,除非您不需要修改函数并创建其他数据结构。

import functools

MAX_CACHE = 10**7

@functools.lru_cache(MAX_CACHE)
def F(n):
    if n == 1 or n == 2:
        return 1
    else:
        return F(n-2) + F(n - 1)

MAX_CACHE是最近记忆的次数。