为什么以下代码只有空间复杂度O(N)?

时间:2017-01-18 20:40:45

标签: algorithm time-complexity space-complexity

这是直接来自Gayle Lakmaan McDowell的Cracking the coding采访。

她列出了以下代码:

 int f(int n) {
 if(n<=1){
   return 1;
  }
 return f(n-1) + f(n-1);
}

她对时间复杂度为何为O(2 ^ n)有明确的解释,但为什么这里的空间复杂度只有O(N)?

3 个答案:

答案 0 :(得分:3)

空间复杂性考虑了调用堆栈的使用。该函数在返回之前将自己调用O(N)次,因此调用堆栈将为O(N)深。

更新(感谢@MatthewWetmore):

为了澄清,f(n-1) + f(n-1);表达式中的两个递归调用不是并行执行的。第一个调用完成消耗线性堆栈使用,然后第二个调用消耗相同的堆栈大小。所以没有空间加倍,这与运行时消耗不同(显然每次调用累计)。

答案 1 :(得分:0)

它在系统堆栈中使用那么多空间来进行函数调用 如F(5)将调用F(4),它将调用F(3)

F(5) - > F(4) - > F(3) - > F(2) - > F(1) - >返回值将以反向顺序关闭

因此,对于计算,此空间在堆栈中分配,用于F(5)5堆栈空间,因此对于F(n),空间将为O(N)

答案 2 :(得分:0)

O符号是一种不对称的符号。这意味着符号表明完成算法的时间永远不会超过某个限制,并且它可以低于但是没有指定,它是有界限的。 算法的时间复杂度取决于输入的大小。这可以是{1}一个数字的输入或{1,2}一个输入的两倍大小的输入。这就是n意味着O(n)。这意味着算法具有线性复杂度,这意味着完成算法的时间将是n *某个常数或C * n 您可能会问自己我们如何确定C井这就是为什么我们使用渐近符号我们可以省略C的确切值,这很有用,因为我们可能会看到一个算法可以有一个C根据输入的顺序或一些而变化其他条件。您可能会看到最佳情况scnearios和最坏情况场景,其中复杂性是Cn,最差的是Cnlogn,在这种情况下我们说算法具有O(nlogn)复杂度,这是因为我们将最坏情况场景作为边界。在这种情况下,我们仍然省略C,我们省略了最佳情况Cn。您可以考虑阅读算法手册以获取更多信息,例如计算机编程第1册或Algorithms by Robert Sedgewick。 Sedgewick的这本书使用Java,非常容易理解。

空间复杂度的工作方式相同,但这次我们讨论的是内存空间,有一种称为动态编程的技术,这种技术存储以前的结果,以便您以后可以将它们用作子问题的解决方案。这样我们就可以跳过多次计算子问题所需的时间,但是解决问题所需的内存量增加了典型的例子Change-making problem。您存储了许多解决方案,并且系统存储器所占用的空间也在增加。该问题具有线性空间复杂性,因为解决问题所需的内存量表现为函数Cn。

作为一个例子,这个函数使用n,可以说是内存中的一个空格,1常量是另一个,所以我们可以说内存中的空间是1 + n;在这种情况下,我们说线性函数有一个位移,线性函数是Cn + a,其中C = 1,a = 1.仍然是一个线性函数。 n来自递归,因为我们将需要内存中的n个空格来存储n个数字,因为递归一直下降到1.所以例如假设n = 3.

我们第一次在内存中有3个,因为它在递归中我们将2存储在内存中并且持续1,我们可以说1已经在内存中或者不是因为1所在的空间可能在堆栈上或堆上。这就是为什么我们使用O表示法,这取决于架构实现。因此,虽然有时复杂性可以是1 + n,但它也可以是n,但是说O(n)我们涵盖了两种情况。

如果你对这条线有疑问的话:

f(n-1) + f(n-1);

根据架构,你可能有一个堆栈,或者你可以将它们发送到主内存(没有想到这个架构的例子)并且有一个垃圾收集器清理引用,因为它超出范围,它仍然是线性空间当你存储3 * 2,2 * 2,1 * 2.在这种情况下,它将是2n + 1或2n。还是线性的。但我怀疑你看到这样的东西最像你会有一个堆栈,一旦递归返回它将开始弹出堆栈中的所有变量,最多使用1 + n或n + 1。