線形時間インプレースリフルシャッフルアルゴリズム


15

線形時間インプレースリフルシャッフルアルゴリズムはありますか?これは、いくつかの特に器用な手が実行できるアルゴリズムです。偶数サイズの入力配列を均等に分割してから、2つの半分の要素をインターリーブします。

Mathworldには、リフルシャッフルに関する簡単なページがあります。特に、入力配列1 2 3 4 5 6を1 4 2 5 3 6に変換するout-shuffleに興味があります。定義では、入力長はことに注意してください2n。

サイズn以上の便利な2番目の配列がある場合、線形時間でこれを実行するのは簡単です。最初に最後のn要素を配列にコピーします。次いで、0ベースのインデックスを仮定すると、最初のコピーnインデックスから要素を[0,1,2,...,n−1]に[0,2,4,...,2n−2]。次に、nをコピーしますn入力配列、マッピングインデックスに二番目の配列の後ろからの要素[0,1,2,...,n−1]に[1,3,5,...,2n−1]。(入力の最初と最後の要素が移動しないため、それよりもわずかに少ない作業を行うことができます。)

これをインプレースで実行しようとする1つの方法は、順列をばらばらのサイクルに分解し、各サイクルに従って要素を再配置することです。繰り返しますが、0ベースのインデックス付けを想定すると、6要素の場合に含まれる順列は

σ=(012345024135)=(0)(5)(1243).

予想どおり、最初と最後の要素は固定小数点であり、中間の4つの要素を入れ替えると、期待される結果が得られます。

残念ながら、順列の数学(およびその)はほとんどウィキペディアに基づいており、これが線形時間で行えるかどうかはわかりません。このシャッフルに含まれる順列はすぐに分解できるのでしょうか?また、完全な分解も必要ありません。それぞれの要素からサイクルを再構築できるため、互いに素なサイクルのそれぞれの単一の要素を決定するだけで十分です。たぶん、まったく異なるアプローチが必要です。LATEX

関連する数学の優れたリソースは、アルゴリズムと同じくらい価値があります。ありがとう!


ある(と時間ソリューションO (1 )余分なスペースが)。私は線形時間の解決策を知りません。O(nlg⁡n)O(1)
— ラドゥグリゴール

4
それはcs.stackexchangeにより適しています。不均一モデルでは、回は常に可能です。この場合、均一にさえ可能であるべきです。O(n)
— ユヴァルフィルマス

1
@Radu この質問と同様に、この問題にはおそらく追加スペースのみを使用する解決策はなく、O (log n )の追加スペースが使用されます。O(1)O(log⁡n)
— タイソンウィリアムズ

2
私はコメントを取り戻します(そして、閉じるために投票します)!(質問は文献で回答されています。)
— ユヴァルフィルマス

1
先週、CSの学生からこの質問を聞きました。CSの学生は就職の面接でそれを聞きました。
— ジェフ

回答:


12

問題は驚くほど簡単ではありません。完全シャッフル(セクション7)による、その場での安定したマージ、エリスとマルコフによる優れたソリューションを次に示します。完全シャッフル順列でサイクルを計算するエリス、クラーン、およびファンは、より多くのメモリを犠牲にして「サイクルリーダー」を選択することに成功しました。また、Fich、Munro、Poblete、Permuting In Placeによる素晴らしい論文も関連しています。これは、オラクルモデルの一般的な時間アルゴリズムを提供します。順列のオラクルのみが利用可能な場合、アルゴリズムは対数空間を必要とします。逆のオラクルもある場合は、一定のスペースが必要です。O(nlog⁡n)

次に、エリスとマルコフのソリューションについて説明します。まず、と仮定します。次に、次数nの完全シャッフルを計算すると、回転が先行する次数xとyの完全シャッフルが計算されます。例による証明(n = 5、x = 3、y = 2): 012 345 67 89 012 567 34 89 051627 3849n=x+ynxyn=5x=3y=2

012345678901256734890516273849

エリスとマルコフは、一定の空間と線形時間を使用して、ときに完全なシャッフルを計算する簡単な方法を見つけました。これを使用して、任意のnの完全シャッフルを計算するアルゴリズムを取得します。まず、書き込みN = 2 K 0 + ⋯ + 2 K Wのバイナリエンコーディング使用nは、およびlet N iは = 2 K I + ⋯ + 2 K Wを。中央のn 0ビットを回転し、右側の2 kをシャッフルしますn=2knn=2k0+⋯+2kwnni=2ki+⋯+2kwn0ビット。右側の2 k 0ビットを無視し、中央のn1ビットを回転させ、右側の2 k 1ビットをシャッフルします。等々。回転は最初のいくつかの要素がサイクルリーダーとして機能するため、簡単に回転できることに注意してください。n t + 1 <nt/2であるため、回転の全体的な複雑さはO(n0+⋯+nw)=O(n)です。内部シャッフルの複雑さはすべてO(2k02k0n12k1O(n0+⋯+nw)=O(n)nt+1<nt/2。O(2k0+⋯+2kw)=O(n)

場合の完全なシャッフルの計算方法を示すために残ります。実際、ネックレスの古典的な研究(フレドリックセンとマイオラナ、k色とk- ary de Bruijnシーケンスのビーズのネックレス、フレドリクセンとケスラー、2色のビーズのネックレスを生成するアルゴリズム)に従って、サイクルリーダーを特定することができます)。n=2kkk

接続とは何ですか?シャッフル置換は、バイナリ表現の右シフトに対応すると主張します。: 000 001 010 011 100 101 110 111 000 100 001 101 010 110 011 111の例による証明です。 したがって、サイクルリーダーを見つけるには、次の回転の各等価クラスから1つの代表を見つける必要があります。長さkのバイナリ文字列。上記の論文は、すべてのサイクルリーダーを生成するための次のアルゴリズムを提供します。0 kから開始n=8

000001010011100101110111000100001101010110011111
k0k。各ステップで、ある時点でます。最大のインデックスを探すIゼロビット、除算のKをすることにより、私は得ることkは= D ⋅ I + Ra1…akikik=d⋅i+r(a1…ai−11)da1…arr=0

n=16

0000,0001,0010,0011,0101,0110,0111,1111.

サイクルリーダーが強調表示されます。


3
arxiv.org/abs/0805.1598を使用するAryabhataの回答も参照してください。その論文、Jainによる「インシャッフル用のシンプルなインプレースアルゴリズム」は、同じアイデアを使用していますが、2、の力を使用 3。ポイントは2 原始根モジュロ 3k、それは簡単に見られる 30、…、3kサイクルリーダーです。エリスやマルコフよりもさらに簡単です!
— ユヴァルフィルム

Jainの論文はもう少し簡単だと思いますが、私は以前の論文と、投票数が最も多い以前の投稿を好んでいます。
— ジョニー

6

これはcs.stackexchange.comでのシードの質問であり、回答はこちらです:https ://cs.stackexchange.com/questions/332/in-place-algorithm-for-interleaving-an-array/400#400

:それは紙の説明ですhttp://arxiv.org/abs/0805.1598。

上記のアルゴリズムは、これらすべてに対して一般化されます k-ウェイシャッフル( 2-ここでウェイシャッフル) k 素数のある平方の原始的なルートです(紙のピック 32 にとって k=2)。

その答えは順列を扱っていることに注意してください j→2jモッド2n+1、(つまり、インシャッフル)、それを持つことで、この問題(アウトシャッフル)も簡単に解決できます。


Ha! I completely forgot about that question, even if I participated in the discussion. This means I didn't really understand how it works that time.
— Radu GRIGore

2

What happens if you write down the riffle shuffle as a function? If m is the length of the total array, let n=m−2 be the length of the array after removing the first and last element. Then the shuffled index of index i is f(i)=2⋅i if i≤n/2 and f(i)=2⋅(imodn/2)−1 if i>n/2. Then you can just "pointer jump" through the array, swapping by re-applying the function.

Assuming random access, this would be linear time while requiring O(1) extra words (for storing the value of the array at any given index), and so O(log⁡n) extra space.


Ah, wait. This assumes that all of the values in the riffle permutation lie on the same cycle. This strategy would have to be modified a bit, depending on how many disjoint cycles there are.
— Robert Robere
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.