Problem
The set [1,2,3,...,*n*]
contains a total of n! unique permutations.
By listing and labeling all of the permutations in order, we get the following sequence for n = 3:
"123"
"132"
"213"
"231"
"312"
"321"
Given n and k, return the kth permutation sequence.
Note:
- Given n will be between 1 and 9 inclusive.
- Given k will be between 1 and n! inclusive.
Example 1:
1 | Input: n = 3, k = 3 |
Example 2:
1 | Input: n = 4, k = 9 |
Analysis
题目与全排列有关,要求指定n
和k
,求出n
的全排列中第k
条排列的内容。如果把所有的排列都枚举出来再选第k
个是不可能的,因为复杂度会非常高,而且需要很大的内存存储,所以思路只能是找一下有什么规律,直接利用k
这个值去算出排列。
我们以example2为例,分析一下如何算出来2314
这个排列。假设所有的排列都被列了出来,实际上我们care的是他们的位置,数字排列的特点就是一旦高位确定下来,本身就会形成一个小组。这句话的意思是,对于2314
来说,一旦确认了最高位是2
,那么314
这个组合的位置就是唯一的。基于这个规则,我们就从结果倒推,来看看314
的位置是什么。以2
开头之后,组合数量只有6个,314
就是在六个里面排在第3
个(下标为2)。然后进入下一个循环,确定以3
开头之后,组合数量只有4个,14
在四个里面排在第1
个(下标为0)。继续进入下一个循环,确定以1
开头之后,就只剩下4
了。
看到上面的思路,可以知道有两个信息是很重要的:第一个信息是确定了高位之后,剩下组合数量。这个不难求出,数量就是剩下的数字的阶乘;第二个信息是在某个组里面的位置,这个位置的计算方式是:上一次排名对本组内组合数量取余的结果。继续用上面的例子解释,一开始的排名是9(下标为8),因为后面有3位,所以组内的组合数量是6。8 / 6 = 1
,先确定位置的下标是1,所以就是数字2
,选中了之后需要去除掉这个数字,后面不能再次使用,后续的数字往前靠。然后更新新的组内排名,所以是8 % 6 = 2
,组内排名的下标就是2。进入下一位,因为数字后面有2位,所以组内的组合数是4。2 / 2 = 1
,位置下标是1,所以就是数字3
。然后更新新的组内排名,所以是2 % 2 = 0
,组内排名的下标就是0。进入下一位,因为数字后面有1位,所以组内的组合数是1。0 / 1 = 0
,位置下标就是0,所以就是数字1
。然后更新组内排名,所以是0 % 1 = 0
,组内排名的下标继续是0。进入下一位,因为是最后一个数字了,所以组合数为1。0 / 1 = 0
,位置下标依然是0,所以就是数字4
。到这里因为完成了四位数,所以任务就结束了。
Solution
因为需要用到每个组的组合数量,可以提前计算好阶乘。然后用一个数组记录备用的数字,用完一个之后移除掉,以保持不会重复用到同一个数字。
Code
1 | class Solution { |
Summary
在排列组合的题目里面,这道也算是比较经典的题目。这道题背后的知识是通过除法和取余来做分组排序,掌握这种思路能解决很多类似的题目。希望这篇博客能够帮助到您,感谢您的支持,欢迎转发、分享、评论,谢谢!