【问题标题】:Find Nth term of provided sequence查找所提供序列的第 N 项
【发布时间】:2019-06-15 16:35:16
【问题描述】:

f(0) = p

f(1) = q

f(2) = r

对于 n > 2

f(n) = af(n-1) + bf(n-2) + c*f(n-3) + g(n)

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

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

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

我已经尝试使用递归来解决这个问题。但是这种方式会消耗大量内存。

【问题讨论】:

    标签: algorithm recurrence


    【解决方案1】:

    比递归更好的方法是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 个变量。

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

    【讨论】:

    • 但这仍然不是有效的解决方案。如果n 太大如 10^18 怎么办?
    【解决方案2】:

    问题在于,对于fn > 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)
    

    因此,我们拨打了 1 次 f(5)、1 次 f(4)、2 次 f(3)、4 次 f(2)、3 次 f(1) 和 2 次 f(0) 电话。

    p>

    由于我们多次调用例如f(3),因此意味着每次都会消耗资源,特别是因为f(3) 本身会进行额外调用。

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

    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 会将它存储在缓存中,如果我们第二次调用f(3),我们将永远不会计算f(3) 本身,缓存将返回预先计算的值。

    不过这里可以优化一下,因为我们每次调用f(n-1)f(n-2)f(n-3),我们只需要存储最后三个值,每次根据最后三个计算下一个值值,并移动变量,例如:

    def f(n):
        if n <= 2:
            return (p, q, r)[n]
        f3, f2, f1 = p, q, r
        for i in range(3, n+1):
            f3, f2, f1 = f2, f1, a * f1 + b * f2 + c * f3 + g(i)
        return f1
    

    【讨论】:

    • 在迭代版本中,不应该在当前索引处评估g,而不仅仅是最终的n
    猜你喜欢
    • 1970-01-01
    • 2013-04-07
    • 1970-01-01
    • 2010-11-05
    • 2015-02-21
    • 2012-01-10
    • 2019-11-19
    • 2014-11-04
    • 2013-01-11
    相关资源
    最近更新 更多