力扣60——第k個排列

原題

給出集合 [1,2,3,…,n],其全部元素共有 n! 種排列。git

按大小順序列出全部排列狀況,並一一標記,當 n = 3 時, 全部排列以下:github

1. "123"
2. "132"
3. "213"
4. "231"
5. "312"
6. "321"

給定 n 和 k,返回第 k 個排列。segmentfault

說明:app

  • 給定 n 的範圍是 [1, 9]。
  • 給定 k 的範圍是[1, n!]。

示例 1:ui

輸入: n = 3, k = 3
輸出: "213"

示例 2:spa

輸入: n = 4, k = 9
輸出: "2314"

解法

按照題目所描述的,其實就是按照排列規律,找出相應的數字。code

每一位上能夠存在的可能數字範圍逐漸減小,所以咱們須要記錄一下當前用過哪些數字內存

每一位上前綴數字最終對應的可能性也是一個全排列,好比 n 爲4時,當第1位定下來一個數字,其對應的全部數字組合有 3!,當第2位定下來後,其對應的數字組合就是2!。當你確認的數字越多,其組合也越少。get

直接上代碼:博客

class Solution {
    // 當前數字是否用過,默認爲false,表明沒有用過
    boolean[] used;

    public String getPermutation(int n, int k) {
        used = new boolean[n];

        int all = 1;
        for (int i = n - 1; i > 1; i--) {
            all *= i;
        }

        StringBuilder sb = dfs(n, all, k);
        return sb.toString();
    }

    /**
     * n:當前還剩幾個數字沒有添加
     * all:爲了計算出當前數字屬於第幾組,例如n等於5時,all是4!,這樣k/n就知道是第幾組了
     * k:所求結果是當前組的第幾個
     */
    public StringBuilder dfs(int n, int all, int k) {
        // 組內偏移量
        int offset = k % all;
        // 當前是第幾組
        int groupIndex = k / all + (offset == 0 ? 0 : 1);

        // 在當前沒有被訪問過的數字裏,找第groupIndex個數字
        int i = 0;
        for (; i < used.length && groupIndex > 0; i++) {
            if (!used[i]) {
                groupIndex--;
            }
        }
        // 用當前數字
        StringBuilder result = new StringBuilder().append(i);
        // 標記當前數字已經用過
        used[i - 1] = true;

        // 說明是最後一個數字
        if (n == 1) {
            return result;
        }
                
                // 確認一位數字後,其對應的可能性就在減小
        return result.append(dfs(n - 1, all / (n - 1), (offset == 0 ? all : offset)));
    }
}

提交OK,執行用時:2ms,內存消耗:34.4MB

總結

以上就是這道題目個人解答過程了,不知道你們是否理解了。這道題應該主要就是找規律了,確認好邊界狀況就應該沒什麼問題。

有興趣的話能夠訪問個人博客或者關注個人公衆號、頭條號,說不定會有意外的驚喜。

https://death00.github.io/

公衆號:健程之道

相關文章
相關標籤/搜索