给定一个带整数的数组,每个整数最多离最终位置n个位置,最好的排序算法是什么?
我一直在想这个问题,我似乎无法找到一个好的策略来开始处理这个问题。有人可以指导我吗?
答案 0 :(得分:7)
我将列表(大小为N)拆分为2n个子列表(使用从零开始的索引):
列表0:元素0,2n,4n,...
清单1:元素1,2n + 1,4n + 1,...
......
list 2n-1:elements 2n-1,4n-1,...
这些列表中的每一个都显然已经排序。
现在合并这些列表(一次重复合并2个列表,或者使用每个列表中一个元素的最小堆)。
就是这样。时间复杂度为O(N log(n))。
这在Python中很简单:
>>> a = [1, 0, 5, 4, 3, 2, 6, 8, 9, 7, 12, 13, 10, 11]
>>> n = max(abs(i - x) for i, x in enumerate(a))
>>> n
3
>>> print(*heapq.merge(*(a[i::2 * n] for i in range(2 * n))))
0 1 2 3 4 5 6 7 8 9 10 11 12 13
答案 1 :(得分:1)
Heap Sort对于最初的随机数组/元素集合来说非常快。在伪代码中,这种形式将如下所示:
# heapify
for i = n/2:1, sink(a,i,n)
→ invariant: a[1,n] in heap order
# sortdown
for i = 1:n,
swap a[1,n-i+1]
sink(a,1,n-i)
→ invariant: a[n-i+1,n] in final position
end
# sink from i in a[1..n]
function sink(a,i,n):
# {lc,rc,mc} = {left,right,max} child index
lc = 2*i
if lc > n, return # no children
rc = lc + 1
mc = (rc > n) ? lc : (a[lc] > a[rc]) ? lc : rc
if a[i] >= a[mc], return # heap ordered
swap a[i,mc]
sink(a,mc,n)
对于像“几乎没有独特”的“近乎分类”这样的不同情况,算法可以以不同的方式工作并且更有效。有关各种情况下带动画的算法的完整列表,请参阅this brilliant site。
我希望这会有所帮助。
聚苯乙烯。对于几乎排序的集合(如上所述),插入排序是您的赢家。
答案 2 :(得分:0)
我建议使用comb sort,只需使用等于最大距离(或那里)的间隙尺寸启动它。预计O(n log n)(或者在你的情况下为O(n log d),其中d是最大位移),易于理解,易于实现,并且即使元素移位超出预期也能工作。如果你需要保证执行时间,你可以使用像堆排序这样的东西,但在过去我发现空间或计算时间的开销通常是不值得的,并最终实现几乎任何其他东西。
答案 3 :(得分:0)
自each integer being at most n positions away from its final position
:
1)对于最小整数(也就是最终排序数组中的第0个整数),其当前位置必须在A [0 ... n]中,因为第n个元素是远离第0个位置的n个位置
2)对于第二个最小整数(也就是最终排序数组中的第一个整数,基于零),其当前位置必须为A [0 ... n + 1]
3)对于第i个最小整数,其当前位置必须在A [i-n ... i + n]
我们可以使用一个(n + 1)-size min堆,包含一个滚动窗口来对数组进行排序。你可以在这里找到更多细节: