Skip to content
25 changes: 17 additions & 8 deletions maths/kth_lexicographic_permutation.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
def kth_permutation(k, n):
"""
Finds k'th lexicographic permutation (in increasing order) of
0,1,2,...n-1 in O(n^2) time.
0,1,2,...,n-1 in O(n^2) time.

Examples:
First permutation is always 0,1,2,...n
First permutation is always 0,1,2,...,n-1
>>> kth_permutation(0,5)
[0, 1, 2, 3, 4]

Expand All @@ -14,23 +14,32 @@ def kth_permutation(k, n):
>>> kth_permutation(10,4)
[1, 3, 0, 2]
"""
# Factorails from 1! to (n-1)!
# Factorials from 1! to (n-1)!
if not isinstance(k, int) or not isinstance(n, int):
raise TypeError("k and n must be integers")

if n < 1:
raise ValueError("n must be a positive integer")

factorials = [1]
for i in range(2, n):
factorials.append(factorials[-1] * i)
assert 0 <= k < factorials[-1] * n, "k out of bounds"

max_k = factorials[-1] * n # equals n!
if not (0 <= k < max_k):
raise ValueError("k out of bounds")

permutation = []
elements = list(range(n))

# Find permutation
while factorials:
factorial = factorials.pop()
number, k = divmod(k, factorial)
permutation.append(elements[number])
elements.remove(elements[number])
permutation.append(elements[0])
index, k = divmod(k, factorial)
permutation.append(elements[index])
elements.pop(index)

permutation.append(elements[0])
return permutation


Expand Down
Loading