将具有两个递归调用的函数转换为交互函数

时间:2016-12-31 22:04:33

标签: python python-3.x recursion

我有一个有两个递归调用的函数,我正在尝试将其转换为迭代函数。我已经弄明白我可以通过一个电话很容易地做到这一点,但我无法弄清楚如何合并另一个电话。

功能:

def specialMultiplication(n):
    if n < 2:
        return 1
    return n * specialMultiplication(n-1) * specialMultiplication(n-2)

如果我只有其中一个,那将非常容易:

def specialMult(n, mult = 1):
    while n > 1: 
        (n, mult) = (n-1, n * mult) # Or n-2 for the second one
    return mult

我无法弄清楚如何添加第二个电话以获得正确的答案。谢谢!

3 个答案:

答案 0 :(得分:6)

如果您不介意更改算法的结构,可以自下而上地计算值,从最小值开始。

<h1>

答案 1 :(得分:4)

使用辅助“待办事项列表”将递归转换为迭代函数:

def specialMultiplication(n):
    to_process = []
    result = 1
    if n >= 2:
        to_process.append(n)
        while to_process:  # while list is not empty
            n = to_process.pop()
            result *= n
            if n >= 3:
                to_process.append(n-1)
                if n >= 4:
                   to_process.append(n-2)
    return result
  1. 创建工作清单(to_process
  2. 如果n >= 2,请将n添加到列表
  3. 虽然to_process不为空,但是从列表中弹出项目,乘以结果
  4. 如果n-1 < 2,请勿执行“左”操作(不要附加到工作清单)
  5. 如果n-2 < 2,请勿执行“正确”操作(不要附加到工作清单)
  6. 此方法具有消耗较少堆栈的优点。我已经针对1到25之间的值对递归版本检查了结果,它们是相同的。

    请注意,它仍然很慢,因为复杂度为O(2^n)所以它从n=30开始变得非常缓慢(当n增加1时,时间加倍)。我的笔记本电脑在12秒内计算出n=28

    我在执行泛洪填充算法时成功使用此方法修复了堆栈溢出问题:Fatal Python error: Cannot recover from stack overflow. During Flood Fill但是这里的Blcknght答案更适合,因为它重新考虑了从一开始就计算它的方式。

答案 2 :(得分:2)

OP的函数具有与Fibonacci和Lucas函数相同的递归结构,只是f0,f1和g的值不同:

f(0) = f0
f(1) = f1
f(n) = g(f(n-2), f(n-1), n)

这是recurrence relation的示例。这是一般解决方案的迭代版本,以n步计算f(n)。它对应于自下而上的尾递归。

def f(n):
    if not isinstance(n, int):  # Can be loosened a bit
        raise TypeError('Input must be an int')  # Can be more informative
    if n < 0:
        raise ValueError('Input must be non-negative')
    if n == 0: 
        return f0
    i, fi_1, fi = 1, f0, f1  # invariant: fi_1, fi = f(i-1), f(i)
    while i < n:
        i += 1
        fi_1, fi = fi, g(fi_1, fi, n)  # restore invariant for new i
    return fi

Blckknight的回答是这个

的简化版本