Giả sử rằng chúng ta đang nói về thứ tự từ vựng trên các giá trị được hoán vị, có hai cách tiếp cận chung mà bạn có thể sử dụng:
- biến đổi một hoán vị của các phần tử thành hoán vị tiếp theo (như ShreevatsaR đã đăng), hoặc
- tính trực tiếp
n
hoán vị thứ, đồng thời đếm n
từ 0 trở lên.
Đối với những người (như tôi ;-) không nói c ++ như người bản xứ, cách tiếp cận 1 có thể được thực hiện từ mã giả sau, giả sử lập chỉ mục dựa trên 0 của một mảng có chỉ mục 0 ở "bên trái" (thay thế một số cấu trúc khác , chẳng hạn như một danh sách, được "để lại như một bài tập" ;-):
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
Đây là một ví dụ bắt đầu với hoán vị hiện tại của 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
Đối với cách tiếp cận thứ hai (tính toán trực tiếp của n
hoán vị thứ), hãy nhớ rằng có các N!
hoán vị của N
các phần tử. Do đó, nếu bạn là N
các phần tử (N-1)!
hoán vị , các hoán vị đầu tiên phải bắt đầu bằng phần tử nhỏ nhất, các (N-1)!
hoán vị tiếp theo phải bắt đầu bằng phần tử nhỏ nhất thứ hai, v.v. Điều này dẫn đến cách tiếp cận đệ quy sau (một lần nữa trong mã giả, đánh số các hoán vị và vị trí từ 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
Vì vậy, ví dụ, hoán vị thứ 13 của ABCD được tìm thấy như sau:
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
Ngẫu nhiên, việc "loại bỏ" các phần tử có thể được biểu diễn bằng một mảng boolean song song cho biết phần tử nào vẫn còn sẵn dùng, do đó không cần thiết phải tạo một mảng mới trên mỗi lần gọi đệ quy.
Vì vậy, để lặp lại các hoán vị của ABCD, chỉ cần đếm từ 0 đến 23 (4! -1) và tính trực tiếp hoán vị tương ứng.