排序堆栈的算法
Posted
技术标签:
【中文标题】排序堆栈的算法【英文标题】:Algorithm for sorting a stack 【发布时间】:2021-11-02 17:24:05 【问题描述】:给定一个栈,任务是对它进行排序,使得栈顶的元素最大。
示例 1:
输入: 堆栈:3 2 1 输出:3 2 1 示例 2:
输入: 堆栈:11 2 32 3 41 输出:41 32 11 3 2
你的任务:
预期时间复杂度:O(N*N) 预期辅助空间:O(N) 递归。
约束: 1
【问题讨论】:
栈是如何实现的?是否使用了特定的语言? 如果这是家庭作业,你应该使用课程中介绍的方法;你的教授可能会对不同的解决方案感到满意,即使它在客观上更好,如果它不能证明对课程材料的理解 【参考方案1】:您似乎被禁止在训练中使用除堆栈之外的任何数据结构。
您可以使用第二个堆栈对堆栈进行排序。
例如 - 在每个阶段选择最小元素。
弹出顶部元素并将其放入smin
变量中。
弹出所有其他元素。如果当前一个小于smin
,则将smin
推入第二个堆栈并放入新值。
毕竟,将smin
推入空的主堆栈,然后将第二个堆栈中的所有元素移入主堆栈。
重复但进行n-1
步骤(如果您的堆栈没有Count
属性,您可以在移动元素时记住计数)。重复直到所有元素都排序完毕(未排序的剩余大小变为1)
【讨论】:
【参考方案2】:堆栈已预先填充 您可以尝试将堆栈的每个元素弹出到一个数组中(O(n)辅助空间)。根据你最喜欢的排序算法对数组进行排序(有算法可以在 O(nLog(n)))
堆栈为空 改用优先队列:|
【讨论】:
【参考方案3】:如果您能够将最小的元素移动到堆栈的底部,那么您就完成了(因为您可以反复执行此操作,每次都缩小堆栈)。
要将最小的元素移到底部,请将所有元素移至辅助堆栈,但将迄今为止最小的元素分开。当主栈为空时,压入最小的然后所有其他元素。
例如
4 5 2 7|
4 5 2| : 7
4 5|7 : 2
4|5 7 : 2
|4 5 7 : 2
2|4 5 7
2 4|5 7
2 4 5|7
2 4 5 7|
【讨论】:
【参考方案4】:由于挑战提到“递归”,看起来您应该在排序时使用调用堆栈(和堆栈帧)来保存数据。
我会建议一种选择排序算法,其中堆栈有一个未排序,上部和一个已排序下部。一开始,未排序的部分是整个堆栈。然后进行 n 次迭代,在每次迭代中,我们找到未排序部分中的最大值并将其移动到已排序部分的顶部。
更详细地说,在每次迭代中,我们都会执行以下步骤:
递归弹出值,并跟踪遇到的最大值。在每次递归调用时记住当前值是否大于目前发现的最大值。
在未排序部分的底部,推入最大值并停止递归。这使得函数退出时的堆栈大小比进入时大 1。
在退出递归调用时,如果当前值是迄今为止最大的递归值,则检查堆栈是否仍然大于预期:
如果是这样,这意味着该值确实是全部最大值,并且它不应该被推入堆栈再次,因为它被放在了底部。通过不再次推送它,堆栈大小现在在退出时与进入时相等。 如果不是这样,这意味着在递归树的更深处发现了一个更大的值,并且应该再次将当前值推入堆栈。如果当前值不是迄今为止最大的递归值,则只需推回该值。
在此阶段之后,我们将最大值移至堆栈底部。现在将堆栈的“底部”定义为高一个条目,以便保持找到的最小值不变。重复上述步骤,直到达到新的“底部”。
继续像这样提升底部,直到底部与堆栈顶部匹配。这表明堆栈已完全排序。
这是一个 javascript 实现:
function moveMaxDown(stack, bottom, maxValue)
let value = stack.pop();
let len = stack.length; // Memorize length before recursing
if (len > bottom) // Not reached the bottom yet
if (value <= maxValue)
moveMaxDown(stack, bottom, maxValue);
else
moveMaxDown(stack, bottom, value);
if (stack.length > len) return; // Current value was already inserted
else
if (value <= maxValue) stack.push(maxValue); // Extra push
stack.push(value);
function stackSort(stack)
for (let bottom = 0; bottom < stack.length; bottom++)
moveMaxDown(stack, bottom, -Infinity);
return stack;
// demo
console.log(stackSort([3, 2, 1]));
console.log(stackSort([11, 2, 32, 3, 41]));
【讨论】:
以上是关于排序堆栈的算法的主要内容,如果未能解决你的问题,请参考以下文章