leetcode60(第k个排列:数学递归)

给出集合 [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;
                }
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/CY2333333/article/details/108425261