整数を含む配列が与えられ、各整数が最終位置から最大で n 位置離れている場合、最適な並べ替えアルゴリズムは何でしょうか?
私はこれについてしばらく考えていましたが、この問題に対処するための良い戦略が思い浮かびません。誰かが私を案内してもらえますか?
(サイズ N の) リストを 2n 個のサブリストに分割します (0 から始まるインデックスを使用):
リスト 0: 要素 0、2n、4n、...
リスト 1: 要素 1、2n+1、4n+1、...
...
リスト 2n-1: 要素 2n-1、4n-1、...
これらの各リストは明らかにソートされています。
次に、これらのリストをマージします (一度に 2 つのリストを繰り返しマージするか、これらの各リストの 1 つの要素で最小ヒープを使用します)。
それで全部です。時間計算量は 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
ヒープ ソートは、最初はランダムな要素の配列/コレクションに対して非常に高速です。疑似コードでは、この並べ替えは次のように実装されます。
# 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)
「ほぼソート済み」または「少数のユニーク」などのさまざまなケースでは、アルゴリズムの動作が異なり、より効率的になります。さまざまな場合のアニメーションを含むアルゴリズムの完全なリストについては、このすばらしいサイトを参照してください。
これが役立つことを願っています。
Ps。ほぼソートされたセット(上記のコメントのとおり)の場合、挿入ソートが勝者です。
コムソートを使用することをお勧めします。最大距離(またはそのあたり)に等しいギャップサイズから始めてください。O(n log n)(またはあなたの場合はO(n log d)、ここでdは最大変位)、理解しやすく、実装しやすく、要素が予想以上に変位した場合でも機能することが期待されます。保証された実行時間が必要な場合は、ヒープソートのようなものを使用できますが、過去には、スペースのオーバーヘッドや計算時間は通常それだけの価値がなく、他のほとんどのものを実装することになります。