LeetCode 60. Permutation Sequence 簡潔高效的解法

問題

集合[1,2,3……,n]共包含n!不同的排列,把他們從小到大排序可以得到:

"123"
"132"
"213"
"231"
"312"
"321"

現在給定nnkk,找到第kk個全排列。

解析

回溯是解決全排列問題的最最最通用的解法,當然,同樣適用於該問題。但是用回溯解決該問題複雜度實在太高,而且這裏不需要求得所有的全排列,只需要求第kk個全排列,所以我們可以轉變一下思路。我們先看一下第kk個全排列有沒有什麼規律。
當n=3時,前兩個數是1開頭,中間兩個數是2開頭,最後面兩個數是3開頭。那麼當1<=k<=21<=k<=2時,第kk個全排列的第一位是1;依次類推得到k的取值範圍和第一位對應的關係。
我們能不能按照這樣的規律繼續深入下去確定第二位,第三位? 答案是肯定的。假設我們確定了第一位數是1,那麼第二位數在2,3中選,如何選?同樣的,把k的範圍進一步縮小,縮小到是1<=k<=11<=k<=1或者2<=k<=22<=k<=2。問題來了,如何在代碼中體現這種範圍的縮小過程呢?我總不能寫一大堆判定語句吧?下圖詳細地給出瞭如何判斷第ii位的數字:
在這裏插入圖片描述
剩下的就是取商,判斷位置,然後更新更準確的位置,然後取商…

Java代碼

    public String getPermutation(int n, int k) {
        StringBuilder sb = new StringBuilder();
        List<Integer> list = new LinkedList();
        int sum = 1;
        int i=1;
        for(i=1;i<=n;i++){
            sum*=i;
            list.add(i);
        }
        i=i-1;
        while(i>0){
            sum = sum/i;
            int temp = k/sum;
            if(temp*sum==k) {
                sb.append(list.get(temp-1));
                list.remove(temp-1);
                temp = temp-1;
            }
            else {
            	sb.append(list.get(temp));
            	list.remove(temp);
            	}
            k = k - temp*sum;
            i--;
        }
        return sb.toString();
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章