Python 两次调用该方法时尾部递归的解释

Python 两次调用该方法时尾部递归的解释,python,python-3.x,Python,Python 3.x,让我们看看下面的代码: import time def rec1(len): if( len < 2): return 1; return 2*rec1(len-1); def rec2(len): if( len < 2): return 1; return rec2(len-1) + rec2(len-1); def callAndReport(len, method): time1 = time.time() answer

让我们看看下面的代码:

import time

def rec1(len):
    if( len < 2): return 1;
    return 2*rec1(len-1);

def rec2(len):
    if( len < 2): return 1;
    return rec2(len-1) + rec2(len-1);

def callAndReport(len, method):
    time1 = time.time()
    answer = method(len)
    time2 = time.time()
    print("{0} with {1}:{2} in {3:.0f} ms".format(len,method.__name__,answer, (time2-time1)*1000))

if __name__ == '__main__':
   callAndReport(20,rec1)
   callAndReport(20,rec2)
   print('')
   callAndReport(23,rec1)
   callAndReport(23,rec2)
有人能解释一下执行时间差吗?我没有什么想法,但我想确定一下

为了完整性,我最初的问题是下面的方法,它可以很容易地表示为For循环,但这不是重点:

def find11s_rec(len):
    if len<2: return 0
    if len== 2: return 1;   
    return find11s_rec(len-2)+find11s_rec(len-1)+2**(len-2)
因为rec1只使用rec1一次,而rec2使用rec2两次。然后这些内部rec2调用将分别调用rec2两次。函数调用的数量将以指数形式增加。rec1可能使用x个调用,而rec2将使用2^x个调用。在计算机科学术语中,rec1是Ox,而rec2是O2^x。在更复杂的情况下,危险的递归可能是无效的;因此,请使用调试器找出实际执行的操作。

rec1的复杂性为On,而rec2的复杂性为O2^n。这是一个很大的性能差异

rec2(n) = rec2(n-1) + rec2(n-1)
        = (rec2(n-2) + rec2(n-2)) + (rec2(n-2) + rec2(n-2)) = 4 * rec2(n-2)
          ...

rec2(n) = (2^n)*rec2(1)
        = O(2^n)

rec2有所谓的重叠子问题-您正在重复已经完成的工作。尾部递归也不是,这不需要对递归调用的结果执行任何操作。哈!太明显了。我没有想到在随后的通话中会出现“分支”。2^x现在已清除。
rec2(n) = rec2(n-1) + rec2(n-1)
        = (rec2(n-2) + rec2(n-2)) + (rec2(n-2) + rec2(n-2)) = 4 * rec2(n-2)
          ...

rec2(n) = (2^n)*rec2(1)
        = O(2^n)