如果一个编程问题给定了上述条件,而我使用递归解决它,那么我是否违反了约束条件?这可能是因为递归也使用堆栈?这样说对吗?
如果递归的栈深度是常数并且不随输入大小而改变,则递归解决方案可以使用O(1)
的额外空间。
一些编译器可能会进行尾调用优化(TCO),并删除递归调用,如果它们是通过函数执行的任何给定代码路径中的最后一个语句。使用TCO,没有调用堆栈相关的内存开销。
然而,请记住,O(1)
约束可能是被强制施加的,以迫使您选择特定(可能是非递归)算法,因此即使您知道您正在使用的编译器已对您的代码进行了相关转换,依赖于尾调用优化可能是不明智的。至少,如果您依赖它,您应该明确说明并通过参考语言规范、编译器文档和/或适当的反汇编来证明您希望进行TCO的期望。
parse(9)
调用parse(8)
,parse(8)
调用parse(7)
,依此类推,直到每个运算符的优先级都被处理完毕。 - user743382extra allowed space is O(1)
意思是你的程序只能使用固定量的空间,例如 C
。
根据大O符号的定义,这意味着你的程序所需的空间不能取决于输入的大小,尽管 C
可以任意大。
因此,如果递归依赖于输入的 a(通常是这种情况),那么你的程序所需的空间就不是 O(1)
。
进一步澄清:
一个每次总是使用 1 Mb
的程序使用 O(1)
空间。
一个总是使用 1 Tb
的程序也使用 O(1)
空间 b。
一个使用 N Mb
,其中 N
是输入的一部分的程序不使用 O(1)
空间(它使用 O(N)
空间)。
简而言之,当你看到 O(1)
时,心里就默念着 常量。
a. 例如,foo(n) = foo(n - 1),在这里维护函数调用所需的堆栈空间是 O(n)
。
b. 当关于 O
符号的材料评论忽略常数会带来麻烦时,这就是他们所说的。
O(1) ,并且无论输入的大小如何都必须保持恒定,如果您希望以递归方式解决问题,那么它只留下两种可能性:
- 固定深度递归,这意味着限制函数递归的次数。
- 尾递归,这意味着调用函数的递归必须是评估的最后一件事,以触发TCO。 (尾递归优化)粗略地说,这意味着由于递归调用是在函数执行中发生的最后一件事情,因此不会将调用上下文推送到堆栈上,而是将现有的调用上下文覆盖为新的上下文,实际上只使用恒定的堆栈空间量。
O(1)的存储复杂度意味着您的算法必须使用恒定数量的存储空间。也就是说,它在处理10个元素和1000个元素时使用的存储空间应该是相同的。
为了实现这一点,您可能应该使用迭代。
Scheme
强制在所有符合规范的实现中消除尾调用... - DirkO(1)
的空间复杂度...)。 - BakuriuO(1)
,尽管它可能会在时间复杂度上失去优势。请参见https://dev59.com/62ox5IYBdhLWcg3wmFaV - a06e