为什么我们不考虑堆栈帧大小而计算递归过程的空间复杂度?

时间:2013-12-24 11:26:03

标签: java arrays algorithm recursion space-complexity

考虑Merge Sort包含int Array元素的n的情况,我们需要一个额外的大小为n的数组才能执行合并。我们放弃了额外的最后的数组。因此,Merge Sort的空间复杂度为O(n)。 但是如果你看一下递归mergeSort过程,在每个递归调用mergeSort(something)上都会有一个堆栈帧被添加到堆栈中。它确实需要一些空间,对吗?

public static void mergeSort(int[] a,int low,int high)
{
    if(low<high)
    {
        int mid=(low+high)/2;
        mergeSort(a,low,mid);
        mergeSort(a,mid+1,high);
        merge(a,mid,low,high);
    }
}

我的问题是:

  1. 为什么我们不考虑堆栈帧的大小 合并排序复杂度?
  2. 是因为堆栈只包含几个整数变量而且 一个参考,不占用太多内存?
  3. 如果我的递归函数创建一个新的局部数组(假设为int a[]=new int [n];),那会怎样呢?那么在计算空间复杂度时会考虑它吗?

2 个答案:

答案 0 :(得分:3)

堆栈消耗的空间应该被充分考虑,但是有些人可能在这里不同意(我相信一些算法甚至会让复杂性声称忽略这一点 - 这里有一个未解决的相关问题,关于基数排序在这里浮动)。

由于我们在每次递归调用时将数组拆分为一半,因此堆栈的大小为O(log n)

因此,如果我们考虑到这一点,总空间将是O(n + log n),这只是O(n)(因为,在大O符号中,我们可以丢弃渐近较小的项),所以它不会改变复杂性。

对于创建本地数组,应用类似的参数。如果您在每一步创建一个本地数组,最终会得到O(n + n/2 + n/4 + n/8 + ...) = O(2n) = O(n)(因为,在big-O表示法中,我们可以丢弃常数因子),因此也不会改变复杂性。

答案 1 :(得分:1)

因为当你这样做时,你没有计算空间复杂性。这被称为确定:您正在进行测试并尝试通过查看结果来总结空间复杂性。这不是一种数学方法。

是的,你的陈述是正确的。