题目描述:
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:
Input: n = 3, k = 3
Output: "213"
Example 2:
Input: n = 4, k = 9
Output: "2314"
题解
该题其实本质上是一个找规律的题,我们可以试图列出n=4是的全排列,从中一探究竟
- 1 2 3 4
- 1 2 4 3
- 1 3 2 4
- 1 3 4 2
- 1 4 2 3
- 1 4 3 2
- 2 1 3 4
- 2 1 4 3
- 2 3 1 4
- 2 3 4 1
- 2 4 1 3
- 2 4 3 1
- 3 1 2 4
- 3 1 4 2
- 3 2 1 4
- 3 2 4 1
- 3 4 1 2
- 3 4 2 1
从上面的排列可以看出:
第一位每个数字出现次数为6次=3!=(n-1)!
第一位数字确定之后,第二位中剩下的每个数字出现的次数为2次=2!=(n-2)!
第一二位数字确定之后,第三位中剩下的每个数字出现的次数为1次=1!=(n-3)!
第一二三位数字确定之后,第四位中剩下的每个数字出现的次数为1次=0!=(n-4)!
假设将1-->n存储到一个数组中,那么k-th排列的
第一位为数组元素中的第(k/{(n-1)!})位置,取出该元素之后应该将该元素从数组中删除,然后对k应该更新为k%(n-1)!
第二位为数组元素中的第 (k/{(n-2)!})位置,取出对应元素之后应该将该元素从数组中删除,然后将k更新为k%(n-2)!
...
循环直到第n位为止
在循环中多次用到阶乘,因此我们可以将0-(n-1)的阶乘提前算出存储到一个数组中
为了便于操作(存在多次(n-1)元素的删除操作)我们将使用一个ArrayList来进行存储参与排列的数
具体的代码如下
public String getPermutation(int n, int k) {
String res="";
//初始化阶段
List<Integer> numbers = new ArrayList<>();
int[] factorial = new int[n];
for(int i=1;i<=n;i++) {
//将排列用到的数字先存到一个list中
numbers.add(i);
//将阶乘先存到数组里
if(i==1) {
factorial[i-1]=i;
}else {
factorial[i-1]=(i-1)*factorial[i-2];
}
}
--k;
//核心部分
for(int i=1;i<=n;i++) {
int index = k/factorial[n-i];
res+=numbers.get(index);
numbers.remove(index);
k%=factorial[n-i];
}
return res;
}