순열되는 값에 대한 사전 식 순서에 대해 이야기하고 있다고 가정하면 다음과 같은 두 가지 일반적인 접근 방식을 사용할 수 있습니다.
- 요소의 하나의 순열을 다음 순열로 변환합니다 (ShreevatsaR 게시 됨).
- 0에서 위로
n
세면서 th 순열을 직접 계산합니다 n
.
C ++를 네이티브로 사용하지 않는 사람들 (나와 같은 ;-)의 경우, "왼쪽"에 인덱스 0이있는 배열의 제로 기반 인덱싱을 가정하여 다음 의사 코드에서 접근 방식 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)까지 세고 해당 순열을 직접 계산합니다.