İzin verilen değerler üzerindeki sözlük düzeninden bahsettiğimizi varsayarsak, kullanabileceğiniz iki genel yaklaşım vardır:
- elementlerin bir permütasyonunu bir sonraki permütasyona dönüştürmek (ShreevatsaR'ın yayınladığı gibi) veya
- 0'dan yukarıya doğru
n
sayarken doğrudan permütasyonu hesaplayın n
.
Yerel olarak c ++ 'ı konuşmayanlar için (benim gibi ;-) yaklaşım 1, aşağıdaki sözde koddan uygulanabilir, "solda" indeks sıfır olan bir dizinin sıfır tabanlı indekslenmesi varsayılır (başka bir yapının yerine , bir liste gibi "alıştırma olarak bırakılır" ;-):
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'nin mevcut permütasyonuyla başlayan bir örnek:
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
İkinci yaklaşım için (. n
Permütasyonun doğrudan hesaplanması ), elementlerin N!
permütasyonları olduğunu unutmayın N
. Bu nedenle, N
elementleri değiştiriyorsanız , ilk(N-1)!
permütasyon permütasyonlar en küçük elementle (N-1)!
başlamalı , sonraki permütasyonlar ikinci en küçükle başlamalı, vb. Bu, aşağıdaki özyinelemeli yaklaşıma yol açar (yine sözde kodda, permütasyonların ve konumların 0'dan numaralandırılması):
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
Dolayısıyla, örneğin, ABCD'nin 13. permütasyonu aşağıdaki gibi bulunur:
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
Bu arada, öğelerin "kaldırılması", hangi öğelerin hala kullanılabilir olduğunu gösteren paralel bir mantık dizisi ile temsil edilebilir, bu nedenle her özyinelemeli çağrıda yeni bir dizi oluşturmak gerekli değildir.
Dolayısıyla, ABCD'nin permütasyonlarını yinelemek için, 0'dan 23'e (4! -1) kadar sayın ve doğrudan karşılık gelen permütasyonu hesaplayın.