参考:https://blog.csdn.net/jacky_chenjp/article/details/66477538
问题描述
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,3,4)的全排列”
“2+(1,3,4)的全排列”
“3+(1,2,4)的全排列”
“4+(1,2,3)的全排列”
我们已经知道,对于n个数的全排列,有n!种情况。所以,3个数的全排列就有6种情况。
如果我们这里给定的k为14,那么它将会出现在:
“3+(1,2,4)的全排列”
这一情况中。
我们可以程式化地得到这个结果:取k=13(从0开始计数),(n-1)!=3!=6,k/(n-1)!=2,而3在有序序列[1,2,3,4]中的索引就是2。
同理,我们继续计算,新的k=13%6=1,新的n=3,那么1/(n-1)!=2/2=0。在序列[1,2,4]中,索引0的数是1。那么,此时的字符串为”31”。
继续迭代,新的k=1%2=1,新的n=2,那么k/(n-1)!=1/1=1。在序列[2,4]中,索引为1的数是4。那么,此时的字符串为”314”。最后在串尾添上仅剩的2,可以得到字符串”3142”。
经过验算,此串确实是序列[1,2,3,4]的全排列数中第14大的序列。
解题算法:
1. 创建一个长度为n 的数组array,存放对应下标n的阶乘值。
2. 再新建一个长度为n 的数组nums,初始值为nums[i]=i+1,用来存放待选的字符序列。
3. 将得到的k减1后,开始迭代。迭代的规则是:迭代n次,每次选nums数组中下标为k/(n-1)!的数放在字符串的末尾,新的k=k%(n-1)!,新的n=n-1。
4. 最后,返回得到的字符串。
AC代码
public class Solution {
public String getPermutation(int n, int k) {
StringBuilder sb = new StringBuilder();
int[] array = new int[n+1];
int sum = 1;
array[0] = 1;
// array[] = [1, 1, 2, 6, 24, ... , n!]
for (int i=1; i<=n; i++){
sum *= i;
array[i] = sum;
}
// nums[] = [1, 2, 3, ... n]
List<Integer> nums = new LinkedList<>();
for (int i=0; i<n; i++){
nums.add(i+1);
}
k--;
for (int i=1; i<=n; i++){
int index = k / array[n-i];
sb.append("" + nums.get(index));
nums.remove(index);
k = k % array[n-i];
}
return sb.toString();
}
}