问题描述:
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.
分析:看到这道题,我突然想到了之前做的leetcode中next permutation的那题,结果我直接复制进来,然后居然ac了,只是耗时太长了(192ms)。既然选择出满足条件的耗时太长,那么只能是构造出满足条件的数据了。
在构造数据时,我们可以看到,第j个数右边有(n-j)!种选择。即根据这样方式构造出数据来。代码如2:
代码如下:192ms
void reverse(int *nums,int start,int end){
int left = start;
int right = end-1;
int tmp;
while(left<right){
tmp = nums[left];
nums[left] = nums[right];
nums[right] = tmp;
left++;
right--;
}
}
void nextPermutation(int* nums, int numsSize) {
if(numsSize<2)
return;
int i,j;
for(i = numsSize-2;i>=0;i--){
if(nums[i]<nums[i+1])
break;
}
if(i<0){
reverse(nums,0,numsSize);
return;
}
int min = nums[i+1];
int index = i+1;
for(j = i+2;j<numsSize;j++){
if(nums[j]>nums[i]&&nums[j]<=min){
min = nums[j];
index = j;
}
}
nums[index] = nums[i];
nums[i] = min;
reverse(nums,i+1,numsSize);
}
char* getPermutation(int n, int k) {
int *nums = (int *)malloc(sizeof(int)*n);
char *res = (char *)malloc(n+1);
int i;
for(i = 0;i<n;i++){
nums[i] = i+1;
}
for(i = 1;i<k;i++){
nextPermutation(nums,n);
}
res[n] = '\0';
for(i = 0;i<n;i++)
res[i] = nums[i]+'0';
return res;
}
写的不大优美,主要维护三个数组,第一个是nums,其中nums[j] = (n-j-1)*nums[j+1];第二个是origin,其中origin[j] = 1,表示,数j尚未被使用,0表示已经被使用。第三个是res,表示返回值。
代码如下:0ms
void initNums(int *nums,int n){
nums[n-1] = 1;
int i;
for(i = n-2;i>=0;i--)
nums[i] = (n-i-1)*nums[i+1];
nums[n-1] = 0;
}
void initOrigin(char *origin,int n){
int i;
for(i = 0;i<n;i++)
origin[i] = 1;
}
char* getPermutation(int n, int k) {
int *nums = (int *)malloc(sizeof(int)*n);
char* res = (char *)malloc(sizeof(char)*(n+1));
char* origin = (char *)malloc(sizeof(char)*(n+1));
int resIndex = 0;
int i;
initNums(nums,n);
initOrigin(origin,n+1);
k--;
for(i = n-1;i>=0;i--){
if(nums[i]>k)
break;
}
int index = i;
for(i = 0;i<=index;i++){
res[resIndex++] = i+1+'0';
origin[i+1] = 0;//代表不可用
}
int offset = 1;
while(k){
int count = 0;
while(k>=nums[index+offset]){
count++;
k=k-nums[index+offset];
}
offset++;
for(i = index+2;i<=n;i++){
if(origin[i]==0)
continue;
if(!count){
res[resIndex++] = i+'0';
origin[i] = 0;
break;
}
count--;
}
}
//deal with the res
for(i = index+2;i<=n;i++){
if(origin[i]!=0){
res[resIndex++] = i+'0';
origin[i] = 0;
}
}
res[resIndex++] = '\0';
return res;
}