题目
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.
分析
首先想到的是,采用STL库中的标准算法next_permutation(),寻找第k个排列即可,可是提交结果为Time Limited Exceed,显然,必须寻找更优算法。
借鉴了别人的思想,设计如下(原文博客):
数学解法
在n!个排列中,第一位的元素总是(n-1)!一组出现的,也就说如果p = k / (n-1)!,那么排列的最开始一个元素一定是nums[p]。
假设有n个元素,第K个permutation是
a1, a2, a3, ….. …, an
那么a1是哪一个数字呢?
那么这里,我们把a1去掉,那么剩下的permutation为
a2, a3, …. …. an, 共计n-1个元素。 n-1个元素共有(n-1)!组排列,那么这里就可以知道
设变量K1 = K
a1 = K1 / (n-1)!
同理,a2的值可以推导为
a2 = K2 / (n-2)!
K2 = K1 % (n-1)!
…….
a(n-1) = K(n-1) / 1!
K(n-1) = K(n-2) /2!
an = K(n-1)
STL标准算法实现(Time Limited Exceed)
class Solution {
public:
string getPermutation(int n, int k) {
if (n <= 0 || k <= 0 || k > factorial(n))
return "";
vector<int> v;
for (int i = 1; i <= n; i++)
v.push_back(i);
int index = 1;
while (index < k && next_permutation(v.begin(), v.end()))
index++;
string str = "";
for (int i = 0; i < n; i++)
str += IntToStr(v[i]);
str += '\0';
return str;
}
string IntToStr(int n)
{
string str = "";
while (n != 0)
{
str += (n % 10 + '0');
n /= 10;
}
reverse(str.begin(), str.end());
return str;
}
long factorial(int n)
{
if (n <= 1)
return 1;
else
return n * factorial(n - 1);
}
};
AC代码
class Solution {
public:
string getPermutation(int n, int k) {
vector<int> nums(n);
int pCount = 1;
for (int i = 0; i < n; ++i) {
nums[i] = i + 1;
pCount *= (i + 1);
}
k--;
string res = "";
for (int i = 0; i < n; i++) {
pCount = pCount / (n - i);
int selected = k / pCount;
res += ('0' + nums[selected]);
for (int j = selected; j < n - i - 1; j++)
nums[j] = nums[j + 1];
k = k % pCount;
}
return res;
}
};