字典序的应用

一、题目描述

输入n,m,k,表示n个“a”字符,m个“z”字符组成一个字符串,要求出字典序从低到高组成的第k个字符串是什么?

【举例】

n = 2,m = 2,k = 6

则该字符串构成的字典序排列为:

aazz azaz azza zaaz zaza zzaa

第6个字符串为:zzaa

二、题目分析

1)C语言自己写全排列程序

2)使用C++库里的next_permutation函数找下一个较高的排列

三、解题算法

1)使用C语言自己写全排列程序

/***********************************************
author:tmw
date:2018-8-11
************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXSIZE 100
#define swap(x,y,t) (t=x,x=y,y=t)

void reverse( char* array , int start , int end )
{
    while( start < end )
    {
        char temp;
        swap(array[start],array[end],temp);
        start++;
        end--;
    }
}
//字典序排列算法----找到比当前排列字典序大1的新排列
char* dictionary_sort( char* array , int array_len )
{
    //step1:从右至左找寻字符串中第一次出现递减序列的首位字符a[i]
    int i = 0;
    int j = 0;
    for( i = array_len - 2 ; (i >= 0) && array[i] >= array[i+1] ; i-- );//此时i位置上的元素array[i]即为目标元素a

    if( i < 0 )//说明此时已经是最大字典序列
        return NULL;

    //step2:寻找i位置往右的字符中,比a[i]大的所有字符里面最小的字符,记为b[j];
    for( j = array_len-1 ; ( j > i ) && array[j] <= array[i] ; j-- );
    //for循环后,就找到了第二个目标元素b---array[j]

    //step3:交换a[i]与b[j]
    char temp;
    swap(array[j],array[i],temp);

    //step4:把第i+1位到最后部分的字符翻转
    reverse(array,i+1,array_len-1);
    return array;
}

int main()
{
    //n个'a',m个'z',求第k个字典序的数
    int n,m,k;
    scanf("%d %d %d",&n,&m,&k);

    //构建字典序最小的aa..zz..
    char* str = (char*)malloc((m+n)*sizeof(char));
    int i,j;
    for(i=0; i<n; i++)
        str[i] = 'a';
    for(j=0; j<m; j++ )
        str[i+j] = 'z';

    //根据k的位置,输出对应的字典序str
    if( k == 1 )
    {
        printf("%s",str);
        return 0;
    }
    int mm = 0;
    while( (str = dictionary_sort(str,strlen(str)-1)) != NULL )
    {
        mm++;
        if( k-1 == mm )
        {
            printf("%s",str);
            return 0;
        }
    }
    //k超界,则返回-1
    printf("%d",-1);
    return 0;
}

2)使用C++库里的next_permutation函数找下一个较高的排列

/***********************************************
author:tmw
date:2018-8-11
************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>			//包含next_permutation
using namespace std;
#define MAXSIZE 100
int main()
{
    //n个'a',m个'z',第k个字典序的数
    int n,m,k;
    scanf("%d %d %d",&n,&m,&k);

    char* str = (char*)malloc((m+n)*sizeof(char));

    int i,j;
    for(i=0; i<n; i++)
        str[i] = 'a';

    for(j=0; j<m; j++ )
        str[i+j] = 'z';

    int mm = 0;

    if( k == 1 )
    {
        printf("%s",str);
        return 0;
    }

    while(next_permutation(str,str+m+n))
    {
        mm++;
        if( k-1 == mm )
        {
            printf("%s",str);
            return 0;
        }
    }

    if( k > mm+1 )
    {
        printf("%d",-1);
        return 0;
    }
}

                                                                                                 梦想还是要有的,万一实现了呢~~~~~ヾ(◍°∇°◍)ノ゙~~~~~~~~~~~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值