繁体   English   中英

求和的递归实现的空间和时间复杂度 function

[英]Space and time complexity of recursive implementation of summation function

谁能建议以下代码的空间和时间复杂度? 我知道时间复杂度应该是 O(n) 因为 function 被调用 n 次,空间复杂度至少是 O(n) (因为堆栈空间),但是将 a[1:] 传递给 function 会导致空间复杂度增加? 我认为 a[1:] 会在省略第一个元素同时创建一个新的副本,对吗?

def sum(a):
    if len(a) == 1:
        return a[0]
    return a[0] + sum(a[1:])

时间复杂度类似于 theta(n^2) ,因为每次执行 a[i:] 时,基本上都会将列表从 i 复制到末尾,因此您必须遍历它。 至于空间复杂度,应用程序堆栈将包含您将调用的所有列表,首先是一个包含 n 个元素的列表,然后是 n-1,依此类推,直到 1,您将开始清空堆栈。 所以你最终也会得到一个 theta(n^2) 复杂度。

作为一个递归的 function,如果没有应用尾调用优化,考虑到它在 memory 堆栈上的执行,在这种情况下肯定会有至少O(n)的空间复杂度。 但是让我们进一步分析一下:

时间复杂度

我们知道 sum 是递归的,它的停止条件是输入数组为单长度时。 所以我们知道Sum在最坏的情况下至少会被调用O(n)次,考虑到一个大小为n的输入数组。 考虑一下它的递归,即循环

然而,在 function 内部,我们有一个切片操作。 切片操作l[a:b]O(ba) ,因此此操作在第一次运行时的复杂度为O(n-1) ,在第二次运行时复杂度为 O( O(n-2) ,依此类推。 我们最初认为,它将执行整个数组的副本。 这个 function 的整体时间复杂度应该是O(n^2)因为它在大小为n的数组中为每个项目创建一个切片。

空间复杂度

现在讨论 memory 中的空间。

len(a) == 1

这里我们有一份来自 len(a) 的返回值的副本。

return a[0]

&

    return a[0] + sum(a[1:])

在上面的两行中,我们将有一个值的另一个副本,它将存储到 function 的返回地址中。 该切片还具有O(n)空间复杂度。

看到这一点,并考虑到编译器没有应用重大优化优化,例如减少,我们说这个 function 的空间复杂度为O(n) ,因为它将为每个输入生成恒定数量的副本并且将在大小为n的数组中执行切片操作。

由于我们一开始说过递归就像一个循环,考虑到没有尾调用优化,整个 function 在最坏的情况下将执行n次。 该程序将增加函数的 memory 堆栈,直到它达到停止条件,直到它最终可以从调用堆栈中“弹出”返回值。 因此,总空间复杂度也是O(n*log n) (因为每次执行输入数组都更小)。

附言:

根据这个,我还认为len(a)具有O(1)时间复杂度。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM