Python递归非常慢

时间:2017-12-20 15:46:46

标签: python python-3.x recursion

我是python的新手,但对这个递归调用执行速度有多慢感到惊讶:

def daH(m:int):
    if m == 1:
        return int(1)
    else:
        if m <= .5 * (daH(m-1) * (daH(m-1) +1)):
            return int(daH(m-1))
        else:
            return int(daH(m-1) + 1)

print(daH(10)) # prints 4
print(daH(11)) # prints 5
print(daH(15)) # prints 5    
print(daH(16)) # prints 6

print(daH(106)) # prints ??? (gave up waiting)    

我在IDLE,python 3.6上运行它。我添加了INT的东西,但它没有帮助。运行标准阶乘递归和打印阶乘(106)没有问题。

这种递归尝试能否得到挽救?

3 个答案:

答案 0 :(得分:14)

您计算daH(m-1) 3次,使算法慢于必要。相反,只计算一次并将结果绑定到局部变量。 (另外,没有必要转换为int

def daH(m:int):
    if m == 1:
        return 1
    else:
        r = daH(m-1)
        if m <= .5 * r * (r + 1):
            return r
        else:
            return r + 1

调用该函数三次而不是一次可能看起来不多,但请记住,这些调用将呈指数级堆叠!你调用它三次,每个再次调用它三次,依此类推。这导致O(3 m )的复杂性,即使m=15导致大约15 百万递归调用,而不是实际的15必要的。

答案 1 :(得分:3)

由于daH是一个数学函数,并且总是为给定的输入生成相同的输出,因此可以缓存这些值并使用它们。

示例输出

$ time python use_cache.py
4
5
5
6
15

real    0m0.194s
user    0m0.144s
sys 0m0.047s
$

缓存装饰器

$ cat use_cache.py
def use_cache_when_possible(func):
    cache = {}
    def foo(*args):
        if args not in cache:
            cache[args] = func(*args)
        return cache[args]
    return foo

@use_cache_when_possible
def daH(m):
    if m == 1:
        return int(1)
    else:
        if m <= .5 * (daH(m-1) * (daH(m-1) +1)):
            return int(daH(m-1))
        else:
            return int(daH(m-1) + 1)

print(daH(10))
print(daH(11))
print(daH(15))
print(daH(16))
print(daH(106))
$

答案 2 :(得分:2)

您正在呼叫daH不必要的次数。

对于每次调用daH(m-1),您的代码会对daH(m)进行3次调用,这会产生指数级复杂性,这会严重缩放,即在较大的m值上执行不正确。

您可以将调用结果保存到daH并在使用相同输入调用daH的地方使用它,而不是多次调用该函数。

def daH(m:int):
    if m == 1:
        return 1
    else:
        ret_val = daH(m-1)
        if m <= .5 * (ret_val * (ret_val +1)):
            return ret_val
        else:
            return ret_val + 1