Dengan asumsi bahwa kita berbicara tentang urutan leksikografik di atas nilai yang diubah, ada dua pendekatan umum yang dapat Anda gunakan:
- mengubah satu permutasi elemen ke permutasi berikutnya (seperti yang diposting ShreevatsaR), atau
- langsung menghitung
n
permutasi th, sambil menghitung n
dari 0 ke atas.
Bagi mereka (seperti saya ;-) yang tidak berbicara c ++ sebagai native, pendekatan 1 dapat diimplementasikan dari pseudo-code berikut, dengan asumsi pengindeksan berbasis-nol dari sebuah array dengan indeks nol di "kiri" (menggantikan beberapa struktur lain , seperti daftar, "ditinggalkan sebagai latihan" ;-):
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
Berikut adalah contoh yang dimulai dengan permutasi CADB saat ini:
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
Untuk pendekatan kedua (perhitungan langsung n
permutasi th), ingatlah bahwa ada N!
permutasi N
elemen. Oleh karena itu, jika Anda mengubah N
elemen, (N-1)!
permutasi pertama harus dimulai dengan elemen terkecil, (N-1)!
permutasi berikutnya harus dimulai dengan yang terkecil kedua, dan seterusnya. Ini mengarah ke pendekatan rekursif berikut (sekali lagi dalam pseudo-code, penomoran permutasi dan posisi dari 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
Jadi, misalnya, permutasi ke-13 ABCD ditemukan sebagai berikut:
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
Kebetulan, "penghapusan" elemen dapat diwakili oleh array paralel dari boolean yang menunjukkan elemen mana yang masih tersedia, sehingga tidak perlu membuat array baru pada setiap panggilan rekursif.
Jadi, untuk mengulangi permutasi ABCD, hitung saja dari 0 hingga 23 (4! -1) dan langsung hitung permutasi yang sesuai.