假设我们正在谈论排列的值的字典顺序,则可以使用两种通用方法:
- 将元素的一个排列转换为下一个排列(如ShreevatsaR发布),或者
- 直接计算
n
n
从0向上计数时,th排列。
对于那些不像本地人那样讲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)计数并直接计算相应的排列即可。