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();

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