LeetCode --- 60. Permutation Sequence
题目链接: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.
这道题的要求是返回由n个数排列组成的第k个序列(n范围是1~9)。
这道题的标签有回溯和数学。但是试了下回溯生成第k个(k已经对n!取模了)序列,超时。又试了试next_permutation函数,还是超时。。
。不知道用回溯怎么做这道题。。。
只是,这确实是一道地地道道的数学问题。
考虑到n个不同数的排列总共同拥有n!种,也就是n-1个数的排列共同拥有(n-1)!种。所以n个数的第k个排列的第一位数字取决于k中包括多少个(n-1)!。即k / (n-1)!。以此类推。第i位上的数字就是剩余k / (n-1-i)!位置上的数字(剩余k是因为k每次对(n-1-i)!取模)。所以仅仅要当前的k除以(n-1-i)!,得到的数字就是当前剩余数组的位置的索引j。
接下来取出该位置元素,并将该位置于i之间的元素都后移1个位置就可以。
实现的时候,k首先须要减1,由于第1个已经生成了。也就是要在第1个的基础上生成第k-1个排列。而用f记录n!。
时间复杂度:O(n2)
空间复杂度:O(n)
1 class Solution
2 {
3 public:
4 string getPermutation(int n, int k)
5 {
6 string s(n, '0');
7
8 int i, j, f = 1;
9 for(i = 0; i < n; ++ i)
10 {
11 s[i] += i + 1;
12 f *= i + 1;
13 }
14
15 for(i = 0, k = (k - 1) % f; i < n; ++ i, k %= f)
16 {
17 f /= n - i;
18
19 int j = i + k / f;
20 char c = s[j];
21 while(j > i)
22 s[j] = s[-- j];
23 s[i] = c;
24 }
25
26 return s;
27 }
28 };