《leetCode》:Permutation Sequence

题目描述

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[n]='\0';
    return result;
}

遇到的问题

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

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

最后AC的结果如下:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值