标签:
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.
集合[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 之间。
对于这个问题可以先考虑给出一个排列怎么求它是第几个排列,然后再从中逆推出第k个排列。要计算一个排列是第几个,只要算出它前面有多少个排列即可。假设n = 5,给出一个排列 35142,那么Nth(35142) = (3-1)*4! + Nth(4132),加号的前半段表示以小于3的1和2开头的排列各有4!个排列,加号右边计算以3开头的剩余有多少个排列。因为3的后面不能再用3了,所以这个问题就等价于求 4132 是第几个排列。如此递归的就可以得到最终结果。
假设 n = 5,令 m = 4!,根据这个计算过程,可以看到第k个排列的首位一定是 (k%m != 0)?(k/m+1):(k/m),剩余的数可以递归或者迭代计算。
每个数需要常数时间确定,所以整个算法时间复杂度是O(n)。给出算法如下:
string getPermutation(int n, int k) { vector<int> p(n+1, 1); for (int i=2; i<=n; ++i) p[i] = p[i-1] * i; vector<bool> used(n+1, false); string ret; for (int i=n; i>=1; --i) { int m = p[i-1]; int t = (k%m != 0)?(k/m+1):(k/m); int j = 1; for (; j<=n; ++j) { if (!used[j]) { --t; if (0==t) { used[j] = true; break; } } } ret.push_back(j+‘0‘); k = (k%m != 0)?k%m:m; } return ret; }
标签:
原文地址:http://www.cnblogs.com/zhiguoxu/p/5491408.html