使用数组的合并排序的空间复杂度

时间:2018-10-20 03:31:51

标签: algorithm time-complexity big-o mergesort

该算法属于mergesort,我知道您可能觉得很奇怪,但我的主要重点是计算该算法的空间复杂度。

如果我们查看mergesort函数的递归树并尝试跟踪算法,则堆栈大小将为log(n)。但是由于merge中也有mergesort函数,该函数正在创建两个大小为n/2n/2的数组,因此我首先应该找到递归关系的空间复杂度,然后再确定,我应该添加将成为n/2 + n/2的{​​{1}}。

我知道答案,但是我对此过程感到困惑。谁能告诉我正确的程序吗?

这种混淆是由于合并函数不是递归的,而是在递归函数中调用的

为什么我们说空间复杂度将为O(log(n) + n)并通过递归函数空间复杂度的定义,我们通常计算递归树的高度

O(log(n) + n)

2 个答案:

答案 0 :(得分:2)

MergeSort时间复杂度是O(nlgn),这是基础知识。合并排序空间的复杂度将始终为O(n)(包括数组在内)。如果您绘制出空间树,则似乎空间复杂度为O(nlgn)。但是,由于该代码是“深度优先”代码,因此您始终只会沿树的一个分支进行扩展,因此,所需的总空间使用将始终由O(3n)= O(n)限制。

例如,如果您绘制出空间树,则好像是O(nlgn)

                         16                                 | 16
                        /  \                              
                       /    \
                      /      \
                     /        \
                    8          8                            | 16
                   / \        / \
                  /   \      /   \
                 4     4    4     4                         | 16
                / \   / \  / \   / \
               2   2 2   2.....................             | 16
              / \  /\ ........................
             1  1  1 1 1 1 1 1 1 1 1 1 1 1 1 1              | 16

其中树的高度为O(logn)=>空间复杂度为O(nlogn + n)= O(nlogn)。但是,在实际代码中情况并非如此,因为它不是并行执行的。例如,在N = 16的情况下,这就是mergesort的代码执行的方式。 N = 16。

                       16
                      /
                     8
                    /
                   4
                 /
                2
               / \
              1   1

注意使用的空间数是32 = 2n = 2 * 16 <3n

然后它向上合并

                       16
                      /
                     8
                    /
                   4
                 /  \
                2    2
                    / \                
                   1   1

,即34 <3n。然后它向上合并

                       16
                      /
                     8
                    / \
                   4   4
                      /
                     2
                    / \ 
                   1   1

36 <16 * 3 = 48

然后向上合并

                       16
                      / \
                     8  8
                       / \
                      4   4
                         / \
                        2   2
                            /\
                           1  1

16 + 16 + 14 = 46 <3 * n = 48

在较大的情况下,n = 64

                 64
                /  \
               32  32
                   / \
                  16  16
                      / \
                     8  8
                       / \
                      4   4
                         / \
                        2   2
                            /\
                           1  1

是64 * 3 <= 3 * n = 3 * 64

对于一般情况,您可以通过归纳证明。

因此,即使您使用数组实现,只要合并后清理使用的空间并且不并行但顺序执行代码,空间复杂度始终由O(3n)= O(n)限制。

我的实现示例如下:

答案 1 :(得分:1)

MergeSort的实现在内存空间上效率很低,并且存在一些错误:

  • 内存没有释放,我假设您依赖垃圾回收。
  • 目标数组Array未被Merge传递给MergeSort

Array为每个递归级别分配了MergeSort大小的额外空间,因此至少是初始数组大小的两倍( 2 * N N * log2(N)空间。这远远超出了要求,因为精心实施可能只占用 N / 2 个额外空间。