Medium!
題目描述:
給出集合 [1,2,3,…,n]
,其所有元素共有 n! 種排列。
按大小順序列出所有排列情況,並一一標記,當 n = 3 時, 所有排列如下:
"123"
"132"
"213"
"231"
"312"
"321"
給定 n 和 k,返回第 k 個排列。
說明:
- 給定 n 的范圍是 [1, 9]。
- 給定 k 的范圍是[1, n!]。
示例 1:
輸入: n = 3, k = 3 輸出: "213"
示例 2:
輸入: n = 4, k = 9 輸出: "2314"
解題思路:
這道題是讓求出n個數字的第k個排列組合,由於其特殊性,我們不用將所有的排列組合的情況都求出來,然后返回其第k個,我們可以只求出第k個排列組合即可,那么難點就在於如何知道數字的排列順序,可參見https://bangbingsyb.blogspot.com/2014/11/leetcode-permutation-sequence.html
首先我們要知道當n = 3時,其排列組合共有3! = 6種,當n = 4時,其排列組合共有4! = 24種,我們就以n = 4, k = 17的情況來分析,所有排列組合情況如下:
1234
1243
1324
1342
1423
1432
2134
2143
2314
2341
2413
2431
3124
3142
3214
3241
3412 <--- k = 17
3421
4123
4132
4213
4231
4312
4321
我們可以發現,每一位上1,2,3,4分別都出現了6次,當第一位上的數字確定了,后面三位上每個數字都出現了2次,當第二位也確定了,后面的數字都只出現了1次,當第三位確定了,那么第四位上的數字也只能出現一次,那么下面我們來看k = 17這種情況的每位數字如何確定,由於k = 17是轉化為數組下標為16:
最高位可取1,2,3,4中的一個,每個數字出現3!= 6次,所以k = 16的第一位數字的下標為16 / 6 = 2,即3被取出
第二位此時從1,2,4中取一個,k = 16時,k' = 16 % (3!) = 4,而剩下的每個數字出現2!= 2次,所以第二數字的下標為4 / 2 = 2,即4被取出
第三位此時從1,2中去一個,k' = 4時,k'' = 4 % (2!) = 0,而剩下的每個數字出現1!= 1次,所以第三個數字的下標為 0 / 1 = 0,即1被取出
第四位是從2中取一個,k'' = 0時,k''' = 0 % (1!) = 0,而剩下的每個數字出現0!= 1次,所以第四個數字的下標為0 / 1= 0,即2被取出
那么我們就可以找出規律了
a1 = k / (n - 1)!
k1 = k
a2 = k1 / (n - 2)!
k2 = k1 % (n - 2)!
...
an-1 = kn-2 / 1!
kn-1 = kn-2 / 1!
an = kn-1 / 0!
kn = kn-1 % 0!
代碼如下:
C++解法一:
1 class Solution { 2 public: 3 string getPermutation(int n, int k) { 4 string res; 5 string num = "123456789"; 6 vector<int> f(n, 1); 7 for (int i = 1; i < n; ++i) f[i] = f[i - 1] * i; 8 --k; 9 for (int i = n; i >= 1; --i) { 10 int j = k / f[i - 1]; 11 k %= f[i - 1]; 12 res.push_back(num[j]); 13 num.erase(j, 1); 14 } 15 return res; 16 } 17 };