สมมติว่าเรากำลังพูดถึงลำดับศัพท์เกี่ยวกับค่าที่ได้รับอนุญาตมีสองวิธีทั่วไปที่คุณสามารถใช้ได้:
- แปลงการเปลี่ยนแปลงหนึ่งขององค์ประกอบเป็นการเรียงสับเปลี่ยนถัดไป (ตามที่ ShreevatsaR โพสต์) หรือ
- คำนวณการ
n
เรียงสับเปลี่ยน th โดยตรงในขณะที่นับn
จาก 0 ขึ้นไป
สำหรับผู้ที่ (เช่นฉัน ;-) ที่ไม่พูด 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
สำหรับแนวทางที่สอง (การคำนวณโดยตรงของการn
เรียงสับเปลี่ยน th) โปรดจำไว้ว่ามีN!
การเรียงสับเปลี่ยนของN
องค์ประกอบ ดังนั้นหากคุณกำลังอนุญาตN
องค์ประกอบการ(N-1)!
เรียงสับเปลี่ยนแรกจะต้องเริ่มต้นด้วยองค์ประกอบที่เล็กที่สุดการ(N-1)!
เรียงสับเปลี่ยนครั้งต่อไปจะต้องเริ่มต้นด้วยค่าที่เล็กที่สุดเป็นอันดับสองเป็นต้น สิ่งนี้นำไปสู่วิธีการเรียกซ้ำต่อไปนี้ (อีกครั้งในรหัสหลอกโดยกำหนดหมายเลขการเรียงสับเปลี่ยนและตำแหน่งจาก 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) และคำนวณการเรียงสับเปลี่ยนที่เกี่ยวข้องโดยตรง