有没有一种只调用一次这个递归函数的有效方法?

Is there an efficient way of invoking this recursive function only once?

这里是一个代码,它可以找到给定值 n 的递归关系给出的函数 T 的值:

def T(n):
  if n <= 0:
    return 1
  else:
    return T(n-1) + (n-1) * T(n-2)
    
print T(3)

#output
2

但是,代码调用函数 T 两次。我在第二个 return 之前添加了 print 语句来显示:

def T(n):
  if n <= 0:
    return 1
  else:
    print (T(n-1) + (n-1) * T(n-2))
    return T(n-1) + (n-1) * T(n-2)
    
print T(3)

#output
1
2
1
2

有没有一种有效的方法可以只调用函数 T 一次?我正在使用 Python 2。我想要简短的东西,不要太复杂。

您将调用 T 2^(n-1) 次,其中 n >1,如果不删除递归,则无法将其减少到仅一次。

如果你的意思是说你想减少重复调用,比如T(3)调用T(2)和T(1),而T(2)也调用T(1),那么你需要使用名为 memoization

的过程

例如,使用结果输入字典。

seen = dict() 

def T(n):
  if n <= 0:
    return 1
  else:
    if n in seen:
        return seen[n] 
    else:
        result = T(n-1) + (n-1) * T(n-2)
        seen[n] = result
        return result 

print(T(3))

您可以将函数从 T(n) = T(n-1) + (n-1)*T(n-2) 重新定义为 T(n+1) = T(n) + n*T(n-1),这将允许递归向前移动而不是向后移动,前提是您给它当前的 n 和以前的值。通过只需要前一个值而不是前两个值,递归级数更容易掌握。

def T(N,n=1,Tm=1,Tn=1):  # n,Tm,Tn represent n,T(n-1),T(n)
    if n>N: return Tm    # stop at n=N+1 and return T(n-1)
    return T(N,n+1,Tn,Tn+n*Tm)

注意:当 n>N 时函数 returns a 是为了覆盖 N 为零的情况。

实际上,这也可以通过将停止条件移动到 N+2 而不是 N+1 来编写而无需转置函数:

def T(N,n=2,Tn_2=1,Tn_1=1):   # n,Tn_2,Tn_1 represent n,T(n-2),T(n-1)
    if n==N+2: return Tn_2    # stop at n=N+2 and return T(n-2)
    return T(N,n+1,Tn_1,Tn_1+(n-1)*Tn_2)

可以进一步简化为:

def T(N,n=1,a=1,b=1): return T(N-1,n+1,b,a*n+b) if N else a