Given a list of elements in lexicographical order (i.e. ['a', 'b', 'c', 'd']), find the nth permutation - Average time to solve?
I stumbled across this interview question:
Given a list of elements in lexicographical order (i.e. ['a', 'b', 'c', 'd']), find the nth permutation
I tried it myself, and it took me about ~30 minutes to solve. (I ended up with a ~8-9 line solution in Python). Just curious -- how long "should" it take to solve this type of problem? Am I taking too long?
9 min, including test
import math
def nthperm(li, n):
n -= 1
s = len(li)
res = []
if math.factorial(s) <= n:
return None
for x in range(s-1,-1,-1):
f = math.factorial(x)
d = n / f
n -= d * f
res.append(li[d])
del(li[d])
return res
#now that's fast...
nthperm(range(40), 123456789012345678901234567890)
Just in case someone is interested in a solution that can find the "i-th" permutation when you look at the "r-length-permutations" (as represented by the r
argument of itertools.permutations
):
from math import factorial
def ith_permutation(i, seq, r=None):
li = list(seq)
length = len(li)
if r is None:
r = length
res = []
current_factorial = factorial(length) // factorial(length - r)
if current_factorial <= i:
raise ValueError('out of range')
for x in range(length, length-r, -1):
current_factorial //= x
div, mod = divmod(i, current_factorial)
i = mod
res.append(li[div])
del(li[div])
return res
For example:
>>> ith_permutationutation(10, [0, 1, 2, 3, 4], 2)
[2, 3]
>>> # correctness check:
>>> from itertools import permutations
>>> list(permutations([0, 1, 2, 3, 4], 2))[10]
(2, 3)
Including a more complete test:
s = range(8)
for n in range(len(s)):
for idx, item in enumerate(permutations(s, n)):
assert list(item) == ith_permutation(idx, s, n)
Some parts of Karoly Horvath's answer were used here.