LeedCode第60题——第K个排列(100%效率,看了绝不后悔的好文)

LeedCode第60题——第K个排列

话不多说先看一下我的算法效率:
LeedCode第60题——第K个排列(100%效率,看了绝不后悔的好文)_第1张图片
题目描述如下:

给出集合 [1,2,3,,n],其所有元素共有 n! 种排列。
按大小顺序列出所有排列情况,并一一标记,当 n = 3, 所有排列如下:
"123"
"132"
"213"
"231"
"312"
"321"
给定 n 和 k,返回第 k 个排列。
示例:输入: n = 3, k = 4
输出: "231"

下面我们以这张图为例来讲解:
LeedCode第60题——第K个排列(100%效率,看了绝不后悔的好文)_第2张图片
我们的思路是采用回溯的方法,在上面这个例子里面我们会先从第一层往后面遍历(也即1,2,3的顺序),我们首先使用一个变量num_before来记录当前位置前面的排列数,那么在看1的时候,他前面是没有排列的,num_beore=0,而以1开头的他最多可以达到的排列次序是:num_before+(n-floor)!=0+(3-1)!=2,也就是他最后的那个排列是132,由于2n=3,这个时候我们的程序就结束了,于是我们最后在n=3,k=4时得到的结果就是231.实现代码如下:

public class Solution {
    public String getPermutation(int n, int k) {
        StringBuilder stringBuilder = new StringBuilder();
        int[] fact = new int[n+1];
        getK(n,k,fact,stringBuilder,0,1);
        return stringBuilder.toString();
    }
    /**
     * @param n 
     * @param k
     * @param fact fact[i]记录数字i是否已用
     * @param stringBuilder 用来记录添加的数字
     * @param num_before 表示当前所在位置前面已有多少个排列
     * @param floor 表示当前所在的层数
     */
    public void getK(int n,int k,int[] fact,StringBuilder stringBuilder,int num_before,int floor){
        if(floor==n+1){
            return;
        }else{
            int num=0;
            for(int i=1;i<=n;i++){
                if(fact[i]==0){
                    if(num_before+getN(n-floor)<k){
                        num_before+=getN(n-floor);
                    }else{
                        stringBuilder.append(i);
                        fact[i]=1;
                        getK(n,k,fact,stringBuilder,num_before,floor+1);
                    }
                }
            }
        }
    }

    int getN(int n){
        if(n==1||n==0){
            return 1;
        }else{
            return n*getN(n-1);
        }
    }
}

LeedCode第60题——第K个排列(100%效率,看了绝不后悔的好文)_第3张图片

你可能感兴趣的:(#,回溯法)