Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 当规定额外允许的空间为O(1)时,这意味着什么?_Algorithm_Recursion_Complexity Theory_Asymptotic Complexity - Fatal编程技术网

Algorithm 当规定额外允许的空间为O(1)时,这意味着什么?

Algorithm 当规定额外允许的空间为O(1)时,这意味着什么?,algorithm,recursion,complexity-theory,asymptotic-complexity,Algorithm,Recursion,Complexity Theory,Asymptotic Complexity,如果在编程问题中给出了上述条件,并且我正在使用递归来解决它,那么我是否违反了约束条件?这可能是因为递归也使用堆栈?是吗?如果递归的深度取决于输入的大小(通常是这样),那么是的:您将使用无限量的堆栈内存。要求使用固定的内存量来解决问题。如果堆栈深度(递归)是恒定的,并且不随输入大小而改变,那么递归解决方案可以是O(1)额外的空间 如果递归调用是通过函数在任何给定代码路径中执行的最后一条语句,则某些编译器可能会执行尾部调用优化(TCO)并删除递归调用。有了TCO,就没有与调用堆栈相关的内存开销 但是

如果在编程问题中给出了上述条件,并且我正在使用递归来解决它,那么我是否违反了约束条件?这可能是因为递归也使用堆栈?是吗?

如果递归的深度取决于输入的大小(通常是这样),那么是的:您将使用无限量的堆栈内存。要求使用固定的内存量来解决问题。

如果堆栈深度(递归)是恒定的,并且不随输入大小而改变,那么递归解决方案可以是
O(1)
额外的空间

如果递归调用是通过函数在任何给定代码路径中执行的最后一条语句,则某些编译器可能会执行尾部调用优化(TCO)并删除递归调用。有了TCO,就没有与调用堆栈相关的内存开销


但是,请记住,O(1)约束可能会强制您选择特定(可能是非递归)算法,因此即使您知道正在使用的编译器已对代码进行了相关转换,依赖尾部调用优化也可能是不明智的。至少,如果您依赖它,您应该明确地说出来,并根据语言规范、编译器文档和/或反汇编(视情况而定)证明您对TCO的期望是正确的。

额外允许的空间是O(1)

这意味着您的程序只能使用恒定的空间量,例如
C

根据big-O的定义,这意味着程序所需的空间不能取决于输入的大小,尽管
C
可以设置为任意大

因此,如果递归依赖于输入a(通常是这种情况),那么程序需要的空间不是
O(1)

进一步澄清:

  • 总是使用
    1MB
    的程序使用
    O(1)
    空间

  • 一个总是使用
    1TB
    的程序正在使用
    O(1)
    空格b

  • 使用
    nmb
    的程序,其中
    N
    是输入的一部分,不使用
    O(1)
    空间(它使用
    O(N)
    空间)

长话短说,每当你读到
O(1)
,就用常量替换它


a。例如,foo(n)=foo(n-1),这里维护函数调用所需的堆栈空间是
O(n)


b。当
O
符号上的材料评论忽略的常数如何会带来麻烦时,这就是他们所说的。

关于其他答案,告诉您必须使用的堆栈量是
O(1)
,并且无论输入的大小都必须保持不变,如果您希望以递归的方式解决问题,那么只剩下两种可能性:

  • 固定深度递归,这意味着限制函数递归的时间
  • 尾部递归,这意味着对函数的递归调用必须是最后一个要计算的内容,以便触发TCO。(尾部调用优化)粗略地说,这意味着由于递归调用是函数执行过程中发生的最后一件事,因此现有的调用上下文将被新的调用上下文覆盖,有效地使用恒定的堆栈空间

如果使用递归来解决此问题,则使用堆栈将数据向下传递到递归树。在这方面,您通常使用多于
O(1)
的空间

我确实同意公认的答案,但我想指出,如果您使用的语言是(如clojure),那么您可以使用
O(1)
空间解决问题,该空间将使用不具有此功能的语言(如java)的更多空间

所以正确的答案也取决于所使用的语言。

O(1)的存储复杂性仅仅意味着您的算法必须使用恒定的存储量。ie在一组10个元素上使用的存储量必须与在1000个元素上使用的存储量相同


您可能应该使用迭代来实现这一点。

不过,这是一种不同寻常的递归。通常,随着输入的增加,它会变得更深。@Thilo一个例子是基于运算符优先级的解析器,其中
parse(9)
调用
parse(8)
,它为每个运算符的优先级调用
parse(7)
等。@delnan,如果移动总数是有界的,那么一个游戏的搜索算法可能有固定数量的调用。@delnan这是我在生产代码中见过的东西,无论如何。至于perreal的例子,如果一个游戏总是向前看(例如)四步,它仍然可以用固定深度的递归实现。尾部递归也可能导致没有堆栈空间用于支持尾部调用消除的语言。从技术上讲,如果你有适当的,那么你可以对一个问题有一个递归解决方案,只需要O(1)堆栈上的空间,与输入无关。递归基本上就是一个循环<例如,代码>方案,要求在所有一致性实现中消除尾部调用……这正是为什么快速排序不是真正的就地算法(如果就地,您的意思是
O(1)
空间复杂度…。@Bakuriu但是快速排序可以编程为循环,并且可以进行
O(1)
空间复杂度,但可能会损失时间复杂度。我非常喜欢关于1Tb常量的评论,我记得很久以前,我问过一位教授我们符号的讲师,“为什么我们不能将每个可能的输入(最大输入大小)计算到一个表中,那么每个问题都可以是O(1)当时我没有得到答案。或者在时间的问题上,为什么不在最坏的情况下保证时间不变的时候睡觉呢