给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。
按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:
“123”
“132”
“213”
“231”
“312”
“321”
给定 n 和 k,返回第 k 个排列。
输入: n = 3, k = 3
输出: “213”
题解:从最小的排列开始,逐渐增大排列,找到第k小的排列。我们需要从最后一个数字开始逐渐往前扩大排列数组大小找前n个的升序排列顺序字符串,例:最前的1个排列是升序排列,最前的2个排列是最后2个数字的升序排列(最后2个数字前面的数字排列顺序为升序),最前6个排列是最后3个数字的升序排列(最后3个数字前面的数字排列顺序为升序)……
我们可以根据示图中展示的规律逐渐逼近第k个排列(如果k大于2小于等于4,则第k个排列的第4个数字一定是5)
class Solution {
//动态字符串记录结果
private final StringBuilder res=new StringBuilder();
public String getPermutation(int n, int k) {
StringBuilder order=new StringBuilder();
for(int i=1;i<=n;i++){
order.append(i);
}
getNum(order,k);
return res.toString();
}
private void getNum(StringBuilder order,int k){
int len=order.length();
if(k==0)
return;
int pos=0;
int preTotal=0;
int numPos=0;
for(int i=1;i<=len;i++) {
int total=0;
int base=1;
//找到第k小的排列
for(int m=1;m<=i-1;m++){
base*=m;
}
for (int j = 1; j <= i; j++) {
total+=base;
if(total>=k){
pos=len-i;
numPos=pos+j-1;
preTotal=total-base;
res.append(order.substring(0,pos)).append(order.charAt(numPos));
order.delete(0,pos).delete(numPos-pos,numPos-pos+1);
getNum(order,k-preTotal);
return;
}
}
}
}
}