60. 第k个排列

问题

在这里插入图片描述

例子
在这里插入图片描述

思路

  • 方法1

    因为for i in range(1,n)时,回溯获取的都是从下到大的,可以采用回溯,同时记录拿到了第几个元素

  • 方法2
    对每一位数进行定位

    第几个按下标的方式: k=k-1
    有个候选数组 list
    未确定的数字有n~1,则某未确定数字后面有n-1~0个数字
    假如给定题目为(5,46)。固定第一位数,后面4位的全排列数为24,46/24==1,即处于候选数组的下标1,取出2并从list中删掉,对于固定第二位数,(46-24*1)/6==4,即处于list的下标4(此时列表移除了已确定的数字2),即第2位数为5.同理,可依次推理出最后结果为“25341”.总复杂度为O(n)

代码

//方法1
class Solution {
    private String res="";
    private int kk=1;//先比较再return,第一个元素是1
    public String getPermutation(int n, int k) {
        StringBuilder sb = new StringBuilder();
        boolean[] used=new boolean[n+1];
        get(n,used,sb,0,k);
        
        return res;

    }

    public void get(int n, boolean[] used, StringBuilder sb, int c, int k) {
        if(c==n && kk==k){
            res=sb.toString();
            kk++;
            return;
            
        }else if(c==n) {
            kk++;
            return;
        }else {
            c++;
            for(int i=1; i<=n; i++) {
                if(!used[i]){
                    sb.append(i);
                    used[i]=true;
                    get(n,used,sb,c,k);

                    sb.deleteCharAt(sb.length()-1);
                    used[i]=false;
                }
            }
        }
        return;
            
        
    }
}

//方法2
class Solution {
    public String getPermutation(int n, int k) {
        StringBuilder sb = new StringBuilder();
        //候选数字
        List<Integer> list = new ArrayList<>();
        //阶乘结果
        int[] jiec = new int[n+1];
        jiec[0]=1;
        int ji=1;
        for(int i=1; i<=n; i++) {
            list.add(i);
            ji*=i;
            jiec[i]=ji;
        }
        k--;//转换为下标模式, i为分母涉及的数字个数
        for(int i=n-1; i>=0; i--) {
            int index=k/jiec[i];//从下标0开始,是第一个,后面有n-1个数字,
            k=k%jiec[i];
            n=n-1;
            sb.append(list.remove(index));

        }
        
        return sb.toString();

    }
    
 
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章