假设我有一个递归函数,该函数适用于具有n
个节点和高度log(n)
的完美平衡二叉树,并在树的根上调用下面的函数。
void printPaths(TreeNode root, int[] array, int depth){
if (root == null){
print array;
}
array[depth] = root.data;
printPaths(root.left, array, depth + 1);
printPaths(root.right, array, depth + 1);
}
array = new int[depthOfTree]
printPaths(root, array, 0);
让数组长度为log(n)
(它将沿树的路径存储值)。我知道递归调用堆栈将是最大高度log(n)
。我不确定的是Java和Java垃圾收集的“传值”性质是如何影响时间和空间复杂性的。
1)将数组传递给递归调用的时间复杂度是多少?如果Java是“按值传递”,那么每个递归调用都会使O(log(n))
在开始任何函数执行之前简单地复制数组吗?
2)在任何时候,有多少这些数组副本在内存中浮动的上限是多少?我倾向于说O(log(n))
。这是否意味着空间复杂度为O(log(n)log(n))
?我在一本书中读到“空间复杂度为O(log(n))
,因为算法将递归O(log(n))
次,并且路径参数仅在递归期间在O(log(n))
空间分配一次”。 / p>
答案 0 :(得分:4)
1)将数组传递给递归调用的时间复杂度是多少?如果Java是“按值传递”,那么每个递归调用是否会在开始执行任何函数之前将O(log(n))简单地复制到数组中?
只是O(1)。 引用按值传递。数组是引用类型(即使数组的元素类型是值类型,例如int[]
)。
因此array
表达式的值不是数组对象本身 - 它只是一个引用。
2)在任何时候,有多少这些数组副本在内存中浮动的上限是多少?
正好1,出于同样的原因。你有一个数组,并且堆栈中的每个级别都有一个对它的引用。
每个递归步骤所占用的唯一额外内存是堆栈上局部变量值的足够空间...这是每次调用的恒定空间量。深度为O(log(N)),这也意味着O(log(N))的空间复杂度。
答案 1 :(得分:1)
1)将数组传递给递归的时间复杂度是多少 呼叫?如果Java是“按值传递”,则每次递归调用都会执行 O(log(n))在启动任何函数之前简单地复制数组 执行?
Java不会复制数组。在Java中,您将Object的引用作为方法中的参数传递。因此,当Object的数据发生变化时,它将反映到所有引用它的引用。