並べ替えられる値に対する辞書式順序について話していると仮定すると、使用できる2つの一般的なアプローチがあります。
- 要素の1つの順列を次の順列に変換する(ShreevatsaRが投稿したように)、または
- 0から上に
n
数えながら、th順列を直接計算しn
ます。
ネイティブとしてc ++を話さない人(私のように;-)の場合、アプローチ1は、「左側」にインデックスがゼロの配列のゼロベースのインデックス付けを想定して、次の擬似コードから実装できます(他の構造に置き換えます)。 、リストなどは「演習として残されます」;-):
1. scan the array from right-to-left (indices descending from N-1 to 0)
1.1. if the current element is less than its right-hand neighbor,
call the current element the pivot,
and stop scanning
1.2. if the left end is reached without finding a pivot,
reverse the array and return
(the permutation was the lexicographically last, so its time to start over)
2. scan the array from right-to-left again,
to find the rightmost element larger than the pivot
(call that one the successor)
3. swap the pivot and the successor
4. reverse the portion of the array to the right of where the pivot was found
5. return
CADBの現在の順列から始まる例を次に示します。
1. scanning from the right finds A as the pivot in position 1
2. scanning again finds B as the successor in position 3
3. swapping pivot and successor gives CBDA
4. reversing everything following position 1 (i.e. positions 2..3) gives CBAD
5. CBAD is the next permutation after CADB
2番目のアプローチ(n
th順列の直接計算)ではN!
、N
要素の順列があることに注意してください。したがって、N
要素を(N-1)!
並べ替える場合、最初の並べ替えは最小の要素で(N-1)!
開始する必要があり、次の並べ替えは2番目に小さい要素で開始する必要があります。これにより、次の再帰的アプローチが行われます(これも疑似コードで、順列と位置に0から番号を付けます)。
To find permutation x of array A, where A has N elements:
0. if A has one element, return it
1. set p to ( x / (N-1)! ) mod N
2. the desired permutation will be A[p] followed by
permutation ( x mod (N-1)! )
of the elements remaining in A after position p is removed
したがって、たとえば、ABCDの13番目の順列は次のようになります。
perm 13 of ABCD: {p = (13 / 3!) mod 4 = (13 / 6) mod 4 = 2
C followed by perm 1 of ABD {because 13 mod 3! = 13 mod 6 = 1}
perm 1 of ABD: {p = (1 / 2!) mod 3 = (1 / 2) mod 2 = 0
A followed by perm 1 of BD {because 1 mod 2! = 1 mod 2 = 1}
perm 1 of BD: {p = (1 / 1!) mod 2 = (1 / 1) mod 2 = 1
D followed by perm 0 of B {because 1 mod 1! = 1 mod 1 = 0}
B (because there's only one element)
DB
ADB
CADB
ちなみに、要素の「削除」は、どの要素がまだ使用可能かを示すブール値の並列配列で表すことができるため、再帰呼び出しごとに新しい配列を作成する必要はありません。
したがって、ABCDの順列を反復処理するには、0から23(4!-1)まで数え、対応する順列を直接計算します。