Solution for Leet Code 60. Permutation Sequence
• By Arman Drismir • 3 minutes readThe set [1, 2, 3, …, n] contains a total of n! unique permutations.
By listing and labeling all of the permutations in ascending order, we get the following sequence for n = 3:
123132213231312321
The solution:
First, think about the problem of generating just the first number of the solution. To help visualize the pattern look at the first digit in the permutation set for n=4.
1 2341 2431 3241 3421 4231 4322 1342 1432 3142 3412 4132 4313 1243 1423 2143 2413 4123 4214 1234 1324 2134 2314 3124 321
We can see that the first number starts at 1, and increments after 6 iterations. For an arbitrary n, how many iterations will it take before the first digit increments?
In general, the first digit increments after (n-1)! iterations.
So after every (n-1)! sized “block” the first digit will increase by 1. Therefore k // (n-1)! (where // is truncated division) will get us the number of “blocks” until the kth permutation. After each block the first digit increments by one, so k // (n-1)! will give us the first digit!
Now we try to find the next digit. If we draw out each block's remaining digits we can see that a similar-ish pattern emerges, where there are "blocks" that start with the same digit.
_ 234_ 243_ 324_ 342_ 423_ 432_ 134_ 143_ 314_ 341_ 413_ 431_ 124_ 142_ 214_ 241_ 412_ 421_ 123_ 132_ 213_ 231_ 312_ 321
The pattern is a little hard to spot, but what is happening is that within each “super-block” of 6 permutations, we have a “sub-block” of size(n-2)!, and within each sub block we increment from 1 to 4, using the numbers that have not already been used by the first digit.
To get the second digit we calculate the size of our “sub-block”, in this case (4-2)! so 2. Then we calculate how many “sub-blocks” into our “super-block” k appears in. The formula for this is (k - super_block_start_index - 1) // sub_block_size.
So we can get how many “sub-blocks” into our “super-block” k appears at, but each “sub-block” has a different number, so how does this help us?
Key insight: Within each “super-block” the first character of the first “sub-block” is always the smallest available number. The first character of the second “sub-block” is always the 2nd smallest available number, etc…
So the second digit is (k - super_block_start_index - 1) // sub_block_size = x where x represents the xth smallest character we can still use.
This process is repeated, dividing the problem into smaller “sub-blocks” until we have resolved each character in the answer.
The final code for the problem is this:
=
=
= 0
= 0
=
= //
+=
+= *
+= 1
return