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.
比较暴力的方法是利用之前写过的nextPermutation,但感觉应该有更好的方法吧。
class Solution {
public:
string getPermutation(int n, int k) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
vector<int> num;
for(int i = 1; i <= n; ++i){
num.push_back(i);
}
for(int i = 1; i< k; ++i){
nextPermutation(num);
}
string res;
for(int i = 0; i < num.size(); ++i){
res += (char)(num[i] + '0');
}
return res;
}
void nextPermutation(vector<int> &num) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
int nSize = num.size();
if (nSize <= 1) return;
int idx = nSize - 1;
// 查找第一个下降的元素
while(--idx >= 0 && num[idx] >= num[idx+1]);
if (idx >= 0)
{
int i = nSize - 1;
// 查找第一个比idx所指元素大的元素
while(num[i] <= num[idx])
{
--i;
}
swap(num[i], num[idx]);
// 反转后面所有元素,让它从小到大sorted
reverse(num.begin()+idx+1, num.end());
}
else
{
reverse(num.begin(), num.end());
}
}
};
果然还是有其他方法的,那就是先算总共有多少种排列组合,然后看k在哪个区间,只要区间确定了,首位的值就确定了。看了个java写的,自己用c++写了一遍,之前那个方法需要1900ms,那个java的方法需要500+ms,现在这个c++实现的只需要20ms就可以过large case。
class Solution {
public:
string getPermutation(int n, int k) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
vector<int> num;
for(int i = 1; i<= n; ++i){
num.push_back(i);
}
vector<int> cnt;
cnt.push_back(1);
for(int i = 1; i<=n;++i ){
cnt.push_back(cnt[i-1] * i);
}
return subPermutation(num, cnt, n, k);
}
string subPermutation(vector<int> &num, vector<int> & cnt, int n, int k){
if(n ==0 || k == 0){
return "";
}
for(int i = 1; i<= n; ++i){
if(k <= cnt[n-1] *i){
int t = num[i-1];
for(int j = i - 1; j < n-1; ++j){
num[j] = num[j+1];
}
return (char)(t+'0') + subPermutation(num, cnt, n - 1, k - (i-1)*cnt[n-1]);
}
}
return "";
}
};
Java实现。
public class Solution {
public String getPermutation(int n, int k) {
int [] fac = new int[n + 1];
fac[0] = 1;
int [] nums = new int[n + 1];
for (int i = 1; i < fac.length; i++) {
fac[i] = i * fac[i - 1];
nums[i] = i;
}
int pos = 0;
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= n; i++) {
int f = n - i;
for (int j = 1; j <= n; j++) {
if (j * fac[f] >= k) {
pos = j;
k -= (j - 1) * fac[f];
break;
}
}
for (int j = 1; j <= n; j++) {
if (nums[j] > 0) {
pos--;
}
if (pos == 0) {
sb.append(nums[j]);
nums[j] = -1;
break;
}
}
}
return sb.toString();
}
}