让我们看一下排列dacb。这在 4 中按字典顺序排列在哪里! = abcd的24个排列?
- 考虑第一个字母
d。在剩余的字母(acb)中,有 3 个字母小于 d,还有 3 个! = 6 个排列,从每个排列开始,总共 18 个排列。
- 考虑前两个字母
da。在剩余的字母 (cb) 中,没有小于 a 的字母(如果有的话,将有 2!= 2 个以 d 开头的排列加上一个),总共 0 个排列。李>
- 考虑前三个字母
dac。在剩余的字母(b)中,有一个字母小于c,还有一个! = 以 dab 开头的 1 个排列,总共 1 个排列。
所以总共有 19 个排列小于dacb。让我们检查一下。
>>> from itertools import permutations
>>> list(enumerate(''.join(p) for p in permutations('abcd')))
[(0, 'abcd'), (1, 'abdc'), (2, 'acbd'), (3, 'acdb'),
(4, 'adbc'), (5, 'adcb'), (6, 'bacd'), (7, 'badc'),
(8, 'bcad'), (9, 'bcda'), (10, 'bdac'), (11, 'bdca'),
(12, 'cabd'), (13, 'cadb'), (14, 'cbad'), (15, 'cbda'),
(16, 'cdab'), (17, 'cdba'), (18, 'dabc'), (19, 'dacb'),
(20, 'dbac'), (21, 'dbca'), (22, 'dcab'), (23, 'dcba')]
看起来不错。所以有4个! − 19 − 1 = 4 个大于dacb 的排列。
现在应该清楚如何概括方法来制作算法了。这是 Python 中的一个实现:
from math import factorial
def lexicographic_index(p):
"""
Return the lexicographic index of the permutation `p` among all
permutations of its elements. `p` must be a sequence and all elements
of `p` must be distinct.
>>> lexicographic_index('dacb')
19
>>> from itertools import permutations
>>> all(lexicographic_index(p) == i
... for i, p in enumerate(permutations('abcde')))
True
"""
result = 0
for j in range(len(p)):
k = sum(1 for i in p[j + 1:] if i < p[j])
result += k * factorial(len(p) - j - 1)
return result
def lexicographic_followers(p):
"""
Return the number of permutations of `p` that are greater than `p`
in lexicographic order. `p` must be a sequence and all elements
of `p` must be distinct.
"""
return factorial(len(p)) - lexicographic_index(p) - 1