Permutation Sequence
The set [1,2,3,…,n]
contains a total of n! unique permutations.
By listing and labeling all of the permutations in order,
We get the following sequence (ie, for n = 3):
"123"
"132"
"213"
"231"
"312"
"321"
Given n and k, return the kth permutation sequence.
Note: Given n will be between 1 and 9 inclusive.
动态规划:f(n)表示有n个数字时,全排列的个数。则:
f(1) = 1;
f(2) = 2 * f(1) = 2;
f(3) = 3 * f(2) = 6;
.
.
.
f(n) = n * f(n-1);
f(1) = 1;
f(2) = 2 * f(1) = 2;
f(3) = 3 * f(2) = 6;
.
.
.
f(n) = n * f(n-1);
分析:
给定n以及排列索引号k。可以得到第k个排列的字符串的倒数第n个位置上的字符为num[⌈k/f(n-1)⌉]。num数组为n个数的升序数组。
之后递归求解倒数第n-1个位置上的字符,此时
n = n-1,
k = k % f(n-1),当 k % f(n-1)不为0时,
k = f(n-1),当k % f(n-1)等于0时。
同理,递归可以求解出待求序列所有位置上的字符。
给定n以及排列索引号k。可以得到第k个排列的字符串的倒数第n个位置上的字符为num[⌈k/f(n-1)⌉]。num数组为n个数的升序数组。
之后递归求解倒数第n-1个位置上的字符,此时
n = n-1,
k = k % f(n-1),当 k % f(n-1)不为0时,
k = f(n-1),当k % f(n-1)等于0时。
同理,递归可以求解出待求序列所有位置上的字符。
举例说明:
输入4 6
初始化num[] = {0, 1, 2, 3, 4};
初始化待求序列 ret= “”;
(1) n = 4, k = 6
⌈k/f(n-1)⌉ = ⌈6/f(3)⌉ = ⌈6/6⌉ = 1;
所以,ret = ret + (‘0’ + num[1]) = “1”;
移除该位置处的值,得到num = {0, 2, 3, 4};
因为k % f(n-1) = 6 % 6 = 0, 所以k = f(n-1) = 6;
(2) n = 3, k = 6;
⌈k/f(n-1)⌉ = ⌈6/f(2)⌉ = ⌈6/2⌉ = 3;
所以,ret = ret + (‘0’ + num[3]) = “1” + “4” = “14”;
移除该位置处的值,得到num = {0, 2, 3};
因为k % f(n-1) = 6 % 2= 0, 所以k = f(n-1) = 2
(3) n = 2, k = 2
⌈k/f(n-1)⌉ = ⌈2/f(1)⌉ = ⌈2/1⌉ = 2;
所以,ret = ret + (‘0’ + num[2]) = “14” + “3” = “143”;
移除该位置处的值,得到num = {0, 2};
因为k % f(n-1) = 2 % 1= 0, 所以k = f(n-1) = 1
(4) n = 1, k = 1;
⌈k/f(n-1)⌉ = ⌈1/f(2)⌉ = ⌈1/1⌉ = 1;
所以,ret = ret + (‘0’ + num[1]) = “143” + “1” = “1432”;
移除该位置处的值,得到num = {0};
此时n – 1 < 1,停止递归。
输入4 6
初始化num[] = {0, 1, 2, 3, 4};
初始化待求序列 ret= “”;
(1) n = 4, k = 6
⌈k/f(n-1)⌉ = ⌈6/f(3)⌉ = ⌈6/6⌉ = 1;
所以,ret = ret + (‘0’ + num[1]) = “1”;
移除该位置处的值,得到num = {0, 2, 3, 4};
因为k % f(n-1) = 6 % 6 = 0, 所以k = f(n-1) = 6;
(2) n = 3, k = 6;
⌈k/f(n-1)⌉ = ⌈6/f(2)⌉ = ⌈6/2⌉ = 3;
所以,ret = ret + (‘0’ + num[3]) = “1” + “4” = “14”;
移除该位置处的值,得到num = {0, 2, 3};
因为k % f(n-1) = 6 % 2= 0, 所以k = f(n-1) = 2
(3) n = 2, k = 2
⌈k/f(n-1)⌉ = ⌈2/f(1)⌉ = ⌈2/1⌉ = 2;
所以,ret = ret + (‘0’ + num[2]) = “14” + “3” = “143”;
移除该位置处的值,得到num = {0, 2};
因为k % f(n-1) = 2 % 1= 0, 所以k = f(n-1) = 1
(4) n = 1, k = 1;
⌈k/f(n-1)⌉ = ⌈1/f(2)⌉ = ⌈1/1⌉ = 1;
所以,ret = ret + (‘0’ + num[1]) = “143” + “1” = “1432”;
移除该位置处的值,得到num = {0};
此时n – 1 < 1,停止递归。
所得待求序列为:1432。
验证:4的全排列为:
1234, 1243, 1324, 1342, 1423, 1432, … 4321。
即所得序列正确。
验证:4的全排列为:
1234, 1243, 1324, 1342, 1423, 1432, … 4321。
即所得序列正确。
1 class Solution 2 { 3 private: 4 vector<int> num; 5 string ret; 6 7 private: 8 int GetSequencesCount(int n) 9 { 10 if(n == 0 || n < 0) return 0; 11 if(n == 1) return 1; 12 13 return n * GetSequencesCount(n-1); 14 } 15 16 void ConstructPermutation(int n, int k) 17 { 18 char ch = '0'; 19 int sub_count = GetSequencesCount(n - 1); 20 int m = 1; 21 22 if(sub_count != 0) 23 { 24 m = k / sub_count; 25 if(k % sub_count != 0) m += 1; 26 k = k % sub_count == 0 ? sub_count : k % sub_count; 27 } 28 29 ch = '0' + num[m]; 30 ret += ch; 31 num.erase(num.begin() + m); 32 33 if(n > 1) 34 ConstructPermutation(n-1, k); 35 } 36 public: 37 string getPermutation(int n, int k) 38 { 39 ret = ""; 40 num.clear(); 41 for(int i = 0; i <= n; i++) 42 num.push_back(i); 43 44 ConstructPermutation(n, k); 45 return ret; 46 } 47 };