题目链接:

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):

  1. "123"
  2. "132"
  3. "213"
  4. "231"
  5. "312"
  6. "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 };