置換される値の辞書式順序について話していると仮定すると、使用できる一般的な方法が 2 つあります。
- 要素の 1 つの順列を次の順列に変換する (ShreevatsaR が投稿したように)、または
- 0 から
n
数えながら th 順列を直接計算します。n
ネイティブとして C++ を話さない人 (私のように ;-) の場合、アプローチ 1 は次の疑似コードから実装できます。「左」にインデックス 0 を持つ配列のゼロベースのインデックス付けを想定しています (他の構造に置き換えます)。 、リストなどは「練習問題として残します」;-):
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
n
2 番目のアプローチ ( 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; ABCD[2] = C}
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; ABD[0] = A}
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; BD[1] = D}
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) まで数えて、対応する順列を直接計算します。