查找提供的序列的第N个术语

时间:2019-06-15 16:35:16

标签: algorithm recurrence

  

f(0)= p

     

f(1)= q

     

f(2)= r

     

对于n> 2

     

f(n)= a f(n-1)+ b f(n-2)+ c * f(n-3)+ g(n)

     

其中g(n)= n * n *(n + 1)

给出p,q,r,a,b,c 问题是,如何找到该系列的第n个术语。

请帮助我为此找到更好的解决方案。

我尝试使用递归解决此问题。但这会消耗大量内存。

2 个答案:

答案 0 :(得分:2)

比递归更好的方法是memoization。您只需要知道f(n)的最后三个值即可。 伪代码的解决方案如下所示:

if n == 0:
    return p
else if n == 1:
    return q
else if n == 2:
    return r
else:    
    f_n-3 = p
    f_n-2 = q
    f_n-1 = r
    for i from 3 to n:
        f_new = a * f_n-1 + b * f_n-2 + c * f_n-3 + g(n)
        fn-1 = fn-2
        fn-2 = fn-3
        fn-3 = f_new

return f_new

这样,您无需递归调用该方法并将所有计算出的值保留在堆栈中,而只需在内存中保留4个变量即可。

这应该计算得更快,并使用更少的内存。

答案 1 :(得分:1)

问题在于,对于每次使用f的{​​{1}}调用,都会导致对n > 2的三个额外调用。例如,如果我们调用f,则会得到以下调用:

f(5)

因此,我们打了一个电话- f(5) - f(4) - f(3) - f(2) - f(1) - f(0) - g(3) - f(2) - f(1) - g(4) - f(3) - f(2) - f(1) - f(0) - g(3) - f(2) - g(5) ,打了一个电话f(5),打了两个电话f(4),打了四个电话f(3),打了三个电话f(2),和两次致电f(1)

由于我们多次调用f(0),因此这意味着每次都将花费资源,尤其是因为f(3)本身会进行额外的调用。

我们可以让Python存储函数调用的结果,并返回结果,例如使用lru_cache [Python-doc]。这种技术称为记忆化

f(3)

这将导致如下调用图:

from functools import lru_cache

def g(n):
    return n * n * (n+1)

@lru_cache(maxsize=32)
def f(n):
    if n <= 2:
        return (p, q, r)[n]
    else:
        return a*f(n-1) + b*f(n-2) + c*f(n-3) + g(n)

因此,现在我们只计算一次- f(5) - f(4) - f(3) - f(2) - f(1) - f(0) - g(3) - g(4) - g(5) f(3)会将其存储在缓存中,如果再次调用lru_cache,我们将永远不会评估{{1} }本身,缓存将返回预先计算的值。

但是,由于我们每次调用f(3)f(3)f(n-1)时,上面的内容可以进行优化,我们只需要存储最后三个值,并每次计算下一个值基于最后三个值,然后移动变量,例如:

f(n-2)