我遇到了以下问题。
给定一组 n 元素和一个整数 k ,其中 k &lt; 名词的。元素{ a 0 ... a k }和 {一 <子>的ķ 1 子> ... 一 <子> 名词 }已经排序了。给出一个算法,在O( n )时间和O(1)空间中进行排序。
在我看来,它不能在O( n )时间和O(1)空间中完成。问题实际上似乎是询问如何进行mergesort的合并步骤,而不是就地。如果有可能,那么不会以这种方式实现mergesort吗?我无法说服自己,但需要一些意见。
答案 0 :(得分:9)
This似乎表明可以在O(lg ^ 2 n)空间中进行。我无法看到如何证明在恒定空间中合并是不可能的,但我也看不出如何做到这一点。
编辑: 追逐参考文献,Knuth Vol 3 - 练习5.5.3说“一个相当复杂的L. Trabb-Pardo算法为这个问题提供了最好的答案:可以在O(n)时间内进行稳定的合并,并在O(n lg n)时间,仅对固定数量的索引变量使用辅助存储器的O(lg n)位。
我还没读过更多references。谢谢你提出了一个有趣的问题。
进一步编辑: 本文声称Huang和Langston的文章有一个算法,它在时间O(m + n)中合并了两个大小为m和n的列表,所以你的问题的答案似乎是肯定的。不幸的是我无法访问该文章,因此我必须信任二手信息。我不确定如何与Knuth关于Trabb-Pardo算法最优的声明进行调和。如果我的生活依赖于它,我会和Knuth一起去。
我现在看到这已被问及早期的Stack Overflow question一次number次。我没有心脏将它标记为副本。
Huang B.-C.和Langston M. A.,实际就地合并,Comm。 ACM 31(1988)348-352
答案 1 :(得分:2)
有几种算法可以做到这一点,其中没有一种很容易直观。关键的想法是使用一部分数组作为缓冲区合并,然后使用此缓冲区进行标准合并以获得辅助空间。如果你可以重新定位元素,以便缓冲元素在正确的位置,你就是黄金。
如果您有兴趣查看,我已在我的个人网站上写了an implementation其中一种算法。它基于Huang和Langston撰写的“实际就地合并”一文。您可能希望查看该论文以获得一些见解。
我也听说有很好的自适应算法,它使用你选择的一些固定大小的缓冲区(如果你想要的话可能是O(1)),但随后用缓冲区大小优雅地扩展。我不知道这些中的任何一个,但我确信快速搜索“自适应合并”可能会有所改变。
答案 2 :(得分:1)
不,这是不可能的,虽然我的工作会更容易,如果是:)。
你有一个你无法避免的O(log n)因子。您可以选择将其作为时间或空间,但避免它的唯一方法是不排序。使用O(log n)空间,您可以构建一个连续列表,以跟踪您隐藏不适合的元素的位置。使用递归,可以使其适合O(1)堆,但这只能使用O(log n)堆栈帧。
以下是从1-9开始合并排序赔率和赔率的进度。请注意您需要如何使用对数空间记帐来跟踪由常量空间和线性交换的双约束引起的顺序反转。
. - 135792468 . - 135792468 : .- 125793468 : .- 123795468 #.:- 123495768 :.- 123459768 .:- 123456798 .- 123456789 123456789
有一些微妙的边界条件,比二元搜索稍微更难以正确,甚至以这种(可能的)形式,因此是一个糟糕的家庭作业问题;但是一个非常好的心理锻炼。
更新的 显然我错了,有一个算法提供O(n)时间和O(1)空间。我已下载论文以启发自己,并将此答案撤回为不正确。