鉴于以下功能:
Element Hello has been added, the list is : [<__main__.StringClass object at 0x1048a0cf8>, None]
Hello
我知道Big O时间复杂度为int f(int n) {
if (n <= 1) {
return 1;
}
return f(n - 1) + f(n - 1);
}
,因为每次调用都会调用该函数两次。
我不明白为什么空间/内存复杂度为O(2^N)
?
答案 0 :(得分:26)
解决这些类型问题的有效方法是考虑recursion tree。要识别的递归函数的两个特征是:
此案例的递归关系为 C
/ \
/ \
T(n-1) T(n-1)
C
____/ \____
/ \
C C
/ \ / \
/ \ / \
T(n-2) T(n-2) T(n-2) T(n-2)
。正如你正确地注意到2^n
的时间复杂度,但让我们看看它与我们的递归树有关。
O(2^n)
此模式将持续到我们的基本情况为止like this。
对于每个连续的树级别,我们的n减少1.因此,我们的树在到达基本情况之前将具有深度n 。由于每个节点有2个分支,并且我们有n个总级别,因此我们的节点总数为O(recursion depth)
,使我们的时间复杂度O(n)
。
我们的内存复杂性由返回语句的数量决定,因为每个函数调用都将存储在程序堆栈中。总而言之,递归函数的内存复杂度为List 1
。正如我们的树深度所示,我们将有n个总返回语句,因此内存复杂度为import Foundation
import RealmSwift
class ShoppingList: Object{
dynamic var listName = ""
var itemList = List<Item>()
}
。
答案 1 :(得分:0)
这是我的想法:
答案 2 :(得分:0)
考虑到其他功能,可以更好地解释这一点
f(n)= f(n-1)+ f(n-2)
f(0)= 0,f(1)= 1
这将导致f(4)的以下计算树
f(4)
f(3)f(2)
f(2)f(1)f(1)f(0)
f(1)f(0)
系统可以使用等于深度的重复存储堆栈(f(0),f(1),f(2),f(3)和f(4)的存储单元来处理计算。尽管运行时需要考虑每个节点上的所有操作(加法或return语句),所以这是不影响任何节点的因素。
答案 3 :(得分:0)
我在两篇文章中找到了明确的答案。
在这个 article 处,它告诉我为什么空间复杂度是 O(n)
。
但我也很困惑为什么 the stack frames
一次只有 f(5) -> f(4) -> f(3) -> f(2) -> f(1)
而没有 f(5) -> f(4) -> f(3) -> f(2) -> f(0)
和其他。
The Fibonacci tree
图像:
然后我终于在第二篇文章中找到了答案,它清除了我的困惑。
在这 article 处很有帮助。您可以在此处查看详细信息。
谢谢。
答案 4 :(得分:-1)
递归问题我们可以认为我们是用栈实现的,所以如果第一个函数调用自己第二个函数pause,它遍历到最后一个一个的加入到栈中,完成后返回并一个个remove从最顶层的堆栈,然后第二个函数恢复并遍历末尾并添加到堆栈的最顶层,并在返回时删除。但是它使用相同的堆栈,并且在同一堆栈下最多占用n个空间,因此使用空间复杂度为O(n)。