Algorithm 合并排序堆栈(仅使用额外堆栈,但根据需要使用尽可能多的堆栈)

Algorithm 合并排序堆栈(仅使用额外堆栈,但根据需要使用尽可能多的堆栈),algorithm,sorting,recursion,heap,Algorithm,Sorting,Recursion,Heap,我正在阅读破解编码面试中的一个问题,作者对标题中描述的问题的解决方案描述如下: 使用合并排序解决方案,我们将创建两个额外堆栈,并将堆栈分成两部分。>部分。我们将递归地对每个堆栈进行排序,然后按排序顺序将它们合并回原始堆栈。请注意,这需要为每个递归级别创建两个附加堆栈 我试图理解时间的复杂性。我假设(尽管可能完全错误)需要两个额外的堆栈,因为当以自下而上的升序合并两个堆栈时,我们必须重复地将两个堆栈中最小的元素弹出到堆栈2中,然后将堆栈2中的所有元素弹出到堆栈1中,以获得所有元素的升序。对于每个递

我正在阅读破解编码面试中的一个问题,作者对标题中描述的问题的解决方案描述如下:

使用合并排序解决方案,我们将创建两个额外堆栈,并将堆栈分成两部分。>部分。我们将递归地对每个堆栈进行排序,然后按排序顺序将它们合并回原始堆栈。请注意,这需要为每个递归级别创建两个附加堆栈


我试图理解时间的复杂性。我假设(尽管可能完全错误)需要两个额外的堆栈,因为当以自下而上的升序合并两个堆栈时,我们必须重复地将两个堆栈中最小的元素弹出到堆栈2中,然后将堆栈2中的所有元素弹出到堆栈1中,以获得所有元素的升序。对于每个递归级别,这个过程都是O(N),因为我们递归地在一半上操作,所以它应该是O(logN)级别,对吗?那么这是一个O(NlogN)时间算法吗?和O(N)空间复杂度?

首先,请注意,创建的每个堆栈的大小都是父堆栈的一半。每个递归级别的堆栈大小之和为N。这使您的空间复杂度为O(N logn)


然而,你可以做得更好。如果在将每个堆栈拆分为两个(向下)后回收每个堆栈,并在合并子堆栈(向上)时回收子堆栈,则确实可以将空间保留为O(N)。

使用4个堆栈和自底向上的合并排序会更快。调用堆栈A、B、C和D,堆栈A上的数据最初为空(B、C、D为空)。将A中的元素(弹出/推送)拆分为C和D(1个元素到C,1个元素到D,…)。然后从C和D合并运行,在A和B之间交替合并运行输出(第一次将2个元素传递到A,将2个元素传递到B,…)。然后merge从A和B运行,交替输出到C和D(在第二个过程中,4个元素到C,4个元素到D,…)。重复此过程,直到只有一个已排序的运行。每次“通过”时,比较的意义都是相反的(C,D->A,B时相反,A,B->C,D时不相反)。B、C、D的大小需要与A相同,除非堆栈是使用单链表实现的。相同的逻辑可以用于4个FIFO队列,只是比较的意义永远不需要颠倒


对于3堆栈自底向上的合并排序,调用堆栈a、B、C,数据最初位于a(B、C为空)上。将A中的元素(弹出/推送)拆分为B和C。然后将B中的元素与C中的元素合并,并将结果推送到A中,从而在A中生成大小为2的排序运行。然后再次拆分A,只是这次在将两个元素从A移到B和将两个元素从A移到C之间交替进行。然后“运行”尺寸为2的管路从B和C合并回A,从而创建尺寸为4的管路。由于元素从A移动到B或C时按相反的顺序推动,因此比较的意义需要颠倒,例如使用>替换