Permutation Sequence — Hard Problem & Solution
The numbers 1, 2, ..., n have n! orderings. Write each ordering as a string of digits and sort them; for n = 3 the list is "123", "132", "213", "231",…
- Difficulty: Hard
- Topics: Math, Recursion
- Asked at: Amazon, Microsoft, Adobe
- Time limit: 2 s
- Memory limit: 256 MB
- Languages: JavaScript, TypeScript, Python, Java, C++, C, C#, Go, Kotlin, Swift, Rust, PHP and Ruby
Problem statement
The numbers 1, 2, ..., n have n! orderings. Write each ordering as a string of digits and sort them; for n = 3 the list is "123", "132", "213", "231", "312", "321".
Return the k-th string in that sorted list (counting from 1).
Example 1
Input: n = 3, k = 3
Output: 213
Example 2
Input: n = 4, k = 9
Output: 2314
Example 3
Input: n = 3, k = 1
Output: 123
Constraints
1 <= n <= 91 <= k <= n!
How to solve Permutation Sequence
The sorted permutations come in blocks: all those starting with the smallest available digit, then the next, and so on, each block of size (remaining - 1)!. Dividing the zero-based index by that block size picks the next digit.
Approach
- Precompute factorials up to
n!and keep the available digits1..nin increasing order. - Let
r = k - 1. Forifromndown to 1:idx = r / (i - 1)!,r = r % (i - 1)!. - Append the
idx-th available digit and remove it from the list. - Return the built string.
Why it works
Among the permutations of the remaining digits, the ones beginning with the j-th smallest digit occupy exactly positions j · (i-1)! to (j+1) · (i-1)! - 1 in sorted order. So the quotient selects the right block and the remainder is the index inside it, recursively.
Complexity
- Time —
O(n^2) (removing from the digit list) - Space —
O(n)
Pitfalls
- Convert
kto a zero-based index first; usingkdirectly is off by one block at every boundary. - Remove each chosen digit from the available list so it is not reused.
- The answer is a string of digits, not a number.
Reference solution
Python
def getPermutation(n: int, k: int) -> str:
fact = [1] * (n + 1)
for i in range(1, n + 1):
fact[i] = fact[i - 1] * i
digits = [str(i) for i in range(1, n + 1)]
r = k - 1
out = []
for i in range(n, 0, -1):
idx = r // fact[i - 1]
r %= fact[i - 1]
out.append(digits.pop(idx))
return ''.join(out)JavaScript
var getPermutation = function(n, k) {
var fact = [1];
for (var i = 1; i <= n; i++) fact.push(fact[i - 1] * i);
var digits = [];
for (var d = 1; d <= n; d++) digits.push(d);
var r = k - 1;
var out = '';
for (var j = n; j >= 1; j--) {
var idx = Math.floor(r / fact[j - 1]);
r %= fact[j - 1];
out += digits[idx];
digits.splice(idx, 1);
}
return out;
};Also on the editorial tab: C, C#, C++, Go, Java, Kotlin, PHP, Ruby, Rust, Swift, TypeScript.
All 307 math problems · the whole catalogue
Learn the technique: Recursion