1. 程式人生 > >Leetcode 60.第k個排列

Leetcode 60.第k個排列

第k個排列

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

按大小順序列出所有排列情況,並一一標記,當 n = 3 時, 所有排列如下:

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

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

說明:

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

示例 1:

輸入: n = 3, k = 3

輸出:

"213"

示例 2:

輸入: n = 4, k = 9

輸出: "2314"

 

提示:

這道題我一上來使用了backtracking的方法依次構造出排列數,當然結果不出所料的TLE了。實際上,仔細觀察這些數字,我們還是不難發現一些規律的。

假設有四位數字{1, 2, 3, 4},那麼他們能夠產生的排列數是什麼呢?

  • 1 + {2, 3, 4}
  • 2 + {1, 3, 4}
  • 3 + {1, 2, 4}
  • 4 + {1, 2, 3}

其實就是選定第一位數字後,其他剩下的數字進行排列組合,就能求出以該數字打頭的所有排列組合。想必已經能發現一些規律了,我們乾脆再舉一個具體的例子,比如我們現在想要找第14個數,那麼由於14 = 6 + 6 + 2。因此第一個數打頭的是3,然後再求{1, 2, 4}中第二個排列組合數,答案是"142"。所以最終答案就是"3142"啦。

這裡有一些問題是需要我們注意的:

  • 構造排列數從最高位開始,當選出一個數字後,就應當把這個數字erase掉,防止後面又出現;
  • 我們所要求的第k個數需要在每次迴圈中減去對應的值;
  • 注意程式中的陣列是從0開始的,但題目的輸入是從1開始計數的。
 1 class Solution{
 2 public:
 3     string getPermutation(int n,int k){
 4         vector<int> permutation(n+1,1);
 5         for(int i=1;i<=n;i++){
 6             permutation[i]=permutation[i-1]*i;
7 } 8 vector<char> digits={'1','2','3','4','5','6','7','8','9'}; 9 int num=n-1; 10 string res; 11 while(num){ 12 int t=(k-1)/(permutation[num--]); 13 k=k-t*permutation[num+1]; 14 res.push_back(digits[t]); 15 digits.erase(digits.begin()+t); 16 } 17 res.push_back(digits[k-1]); 18 return res; 19 } 20 };