运行时间和空间复杂度修改的Mergesort

时间:2018-10-03 20:40:18

标签: algorithm sorting big-o mergesort

这是数据结构和算法课程的家庭作业问题。我不希望有人替我做作业。只是希望有人能告诉我我是否正在适当地解决这个问题。

public static void sort(int[] a) {
  sort(a, 0, a.length - 1);
}

private static void sort(int[] a, int lo, int hi) {
  if (hi <= lo) return;

  int[] aux = new int[a.length];
  int mid = (hi + lo) / 2;
  sort(a, lo, mid);
  sort(a, mid + 1, hi);
  merge(a, lo, mid, hi, aux);
}

private static void merge(int[] a, int lo, int mid, 
 int hi, int[] aux) {

  int i = lo, j = mid + 1;
  for (int k = lo; k <= hi; k++)
    aux[k] = a[k];

  for (int k = lo; k <= hi; k++) {
    if (i > mid)
      a[k] = aux[j++];
    else if (j > hi)
      a[k] = aux[i++];
    else if(aux[j] < aux[i])
      a[k] = aux[j++];
    else
      a[k] = aux[i++];
  }
}

此实现与典型实现(在我们的类中已给出)之间的唯一区别是,在每次递归调用sort时都重新定义了aux数组,而在典型情况下,仅在public sort方法中定义了aux数组案件。典型情况是运行时间为O(nlog(n)),空间复杂度为O(n)。

我的任务是确定所示的mergesort修改实现的运行时间和空间复杂度。据我所知,运行时间没有改变,因此仍然是O(nlog(n)),空间复杂度也是O(nlog(n))。我得出这个结论的逻辑是,sort方法每次被调用时都会分配一个大小为n的数组,它被称为log(n)次。

到目前为止,我在围绕时空和时间的复杂性问题上很难过。我是在正确地考虑这一点吗?还是我要离开?

任何指针都非常感谢。

1 个答案:

答案 0 :(得分:0)

是的,空间复杂度为O(n*logn),但需要澄清。

  

我得出这个结论的逻辑是排序方法   每次调用时分配一个大小为n的数组,并且该数组被调用   总共log(n)次。

实际上,在合并排序期间,sort总共被调用n次,但是在此过程中,最大递归深度为logn。让我们绘制一棵递归调用树:

           sort
          /    \
       sort    sort
        /\       /\
     sort sort sort sort
            ...

在每个级别上,每个sort函数都执行其父级的一半工作。因此,在级别0(根节点)上,sort进行了n次迭代,在级别1上,两种排序各自具有n/2的运行时间(总计为n),级别2的四种类别各有n/4个等。组合起来,每个级别进行n个迭代,并且由于树的深度为log n,因此您得到了O(n*logn)的时间复杂度。

但是,在您的情况下,aux分配n个元素,而不管当前深度如何,并且有n种调用,因此乍一看,可以得出结论:复杂度为O(n*n) = O(n^2)这不是,因为一旦完成每个递归调用,就会释放分配的空间,并且最多有logn个递归调用。

请注意,aux不必要地每次都会分配n个元素的数组。如果您在aux函数中声明merge并设置适当的长度,则可以改进算法,如下所示:

private static void merge(int[] a, int lo, int mid, int hi) {

  int[] aux = new int[hi - lo + 1];     

  int i = lo, j = mid + 1;
  for (int k = lo; k <= hi; k++)
    aux[k - lo] = a[k];

  for (int k = lo; k <= hi; k++) {
    if (i > mid)
      a[k] = aux[j++ - lo];
    else if (j > hi)
      a[k] = aux[i++ - lo];
    else if(aux[j - lo] < aux[i - lo])
      a[k] = aux[j++ - lo];
    else
      a[k] = aux[i++ - lo];
  }
}

HTH。