您的位置:首页 > 产品设计 > UI/UE

《leetCode》:Permutation Sequence

2015-11-22 17:39 495 查看

题目描述

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.


题目大意:找到第k个排列。

思路

与找出n个数的全排列的思路一样,但是这里只需要我们找出第k个排列,因此,设置一个标志位flag,当其为flag为false时,表示已经找到第k个。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
/*
思路:递归法,要注意的是:结果是排序后的第k个结果
*/
void swap(char *a,char *b){
char temp=*a;
*a=*b;
*b=temp;
}
void bubbleSort(char *arr,int begin,int length){
int i,j;
for(i=begin;i<length;i++){
for(j=i+1;j<length;j++){
if(arr[i]>arr[j]){
swap(&arr[i],&arr[j]);
}
}
}
}
bool flag=true;
char *result;
void getPermutate(char *arr,int len,int* k,int start){
if(arr==NULL||len<0){
return ;
}
if(start==len-1){//得到一种结果
if((*k)==1){//得到最终的结果
flag=false;
for(int k=0;k<len;k++){
result[k]=arr[k];
}
result[len]='\0';

}
(*k)--;
}
else{
for(int i=start;i<len;i++){
if(flag){
swap(&arr[start],&arr[i]);
bubbleSort(arr,start+1,len);
getPermutate(arr,len,k,start+1);
if(flag){
bubbleSort(arr,start+1,len);
}

}
}
}

}
char* getPermutation(int n, int k) {
if(n<1||k<1){
return NULL;
}
flag=true;
//开辟一段空间来保存结果
result=(char *)malloc((n+1)*sizeof(char));
if(result==NULL){
exit(EXIT_FAILURE);
}
char *s=(char *)malloc((n)*sizeof(char));
if(s==NULL){
exit(EXIT_FAILURE);
}
for(int i=0;i<n;i++){
s[i]=(char)(i+'1');
//  printf("%c   ",s[i]);
}
getPermutate(s,n,&k,0) ;
return result;
}

int main(void){

int n,k;
while(scanf("%d%d",&n,&k)!=EOF&&n>0&&k>0){
char *result=getPermutation(n,k);

puts(result);
}
return 0;
}


AC结果如下:



小结

虽然AC了,但是效率不高。可以寻找更好的方法来做。

改进

此方法来源于:

思路如下:

http://blog.csdn.net/doc_sgl/article/details/12840715

方法二:数学解法
在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)


实现代码如下:

char* getPermutation(int n, int k) {
if(n<1||k<1){
return NULL;
}
//开辟一段空间来保存结果
char* result=(char *)malloc((n+1)*sizeof(char));
if(result==NULL){
exit(EXIT_FAILURE);
}
//开辟一段空间,来保存1~n的字符
char *s=(char *)malloc((n)*sizeof(char));
if(s==NULL){
exit(EXIT_FAILURE);
}
int count=1; //用来表示n!
for(int i=0;i<n;i++){
s[i]=(char)(i+'1');
count*=(i+1);
}
//求结果中每一位对应的字符
k--;//减一的原因在于:第(n-1)!个排列应该是以1开头的最后一个排列;如果不减一,将会是以2开头的第一个
for(int i=0;i<n;i++){
count=count/(n-i);
int index=k/count;
result[i]=s[index];
for(int j=index;j<n-i-1;j++){//将s后面的元素提前
s[j]=s[j+1];
}
//更新k
k=k%count;

}
result
='\0';
return result;
}


遇到的问题

1、当要求输出第k个排列时,原始代码实现的是:输出第k+1个排列,就报了如下错误。



解决方法:在开始之前,将k减1.//减一的原因在于:第(n-1)!个排列应该是以1开头的最后一个排列;如果不减一,将会是以2开头的第一个

最后AC的结果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: