backtracking
math
]
Leetcode 0060. Permutation Sequence
https://leetcode.com/problems/permutation-sequence
The simplest way to solve this problem is use backtracking, where you just generate all sequences, with complexity O(k) = O(n!). We can do better. Let us consider an example: n=6, k=314. How we can find the first digit? There are 5! = 120 permutations, which start with 1, there are also 120 permutations, which start with 2, and so on. 314 > 2*120 and 314 < 3*120, so it means, that the fist digit we need to take is 3. So we build first digit of our number, remove it from list of all digits digits and continue:
k = 314-2*5! = 74,n - 1 = 5,d = 3, build number so far3,digits = [1,2,4,5,6]k = 74-3*4! = 2,n - 1 = 4,d = 0, build number so far35,digits = [1,2,4,6]k = 2-0*3! = 2,n - 1 = 3,d = 0, build number so far351,digits = [2,4,6]k = 2-1*2! = 0,n - 1 = 2,d = 2, build number so far3512,digits = [4,6]k = 0-1*1! = 0,n - 1 = 1,d = 2, build number so far35126,digits = [4]- Finally, we have only one digit left, output is
351264.
Complexity. I keep list of n digits, and then delete them one by one. Complexity of one deletion is O(n), so overall complexity is O(n^2). Note, that it can be improved to O(n log n) if we use SortedList, but it just not worth it, n is too small.
class Solution:
def getPermutation(self, n, k):
numbers = list(range(1,n+1))
answer = ""
for n_it in range(n,0,-1):
d = (k-1)//factorial(n_it-1)
k -= d*factorial(n_it-1)
answer += str(numbers[d])
numbers.remove(numbers[d])
return answer
Oneliner
Here it is, with O(n^2) complexity!
return reduce(lambda s,n:(s[0]+s[2][(d:=s[1]//(f:=factorial(n)))],s[1]%f,s[2][:d]+s[2][d+1:]),range(n-1,-1,-1),('',k-1,'123456789'))[0]
If you like the solution, you can upvote it on leetcode discussion section: Problem 0060