全排列问题 按字典序全排列字符(通过循环解决 非递归)

题面

给定一个全由小写字母构成的字符串,求它的全排列,按照字典序从小到大输出。

输入格式:
一行,一个字符串,长度不大于8。

输出格式:
输出所有全排列,每行一种排列形式,字典序从小到大。

输入样例:
在这里给出一组输入。例如:

abc

输出样例:
在这里给出相应的输出。例如:

abc
acb
bac
bca
cab
cba

题解

基本想法是找到先将所有的字母按照字典序排序完成 同时建立一个order数组来保存顺序,最初的顺序就是从0到8。然后只要通过对于order数组的变换不断输出就可以得到答案。

通过观察不难发现 对比上一个 下一个就是从末尾开始找,找到第一个仍旧是按照字典序排列的位置 即order[i]<order[i+1]的位置 用end来表示这个位置i 意味着这个位置必定被下一个替换

然后再通过从end到n进行处理 通过一个函数range(int l, int r)。l和r来标识范围 由于仍旧按照字典序排列 所以要找到最小的比order[l]大的那个数字 为了通用性以及能够思路比较清晰所以还是用了循环来解决 其实找order[i]+1好像也可以?(没有实践有待商榷欢迎指正)
然后将这两个数直接进行交换 这样就能够保证l位置 即 end位置的数字的正确 对于end后面的数字再进行排序(比较懒所以直接暴力了 排序可以优化)

这样完成之后下一步又会是最后两个交换 然后最后三个交换以此类推

Talk is cheap show me the code:

#include<stdio.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
int order[9];
char str[9];
void range(int l, int r)
{
    int nexti=l+1;
    for(int i=l+1;i<=r;i++)
    {
        if(order[i]>order[l]&&order[i]<order[nexti])
        {
            nexti=i;
        }
    }//找到要和l交换的位置
    int temp;
    temp=order[l];
    order[l]=order[nexti];
    order[nexti]=temp;
	//完成order[l]位置
    for(int i=l+1;i<=r;i++)
        for(int j=i;j<=r;j++)
        {
            if(order[i]>order[j])
            {
                int tem;
                tem=order[i];
                order[i]=order[j];
                order[j]=tem;
            }
        }
	//对于后面的进行排序
}
void Initorder()
{
    for(int i=0;i<9;i++)
    order[i]=i;
}
void Order(int n){
    int end=n;
    while(order[end]<order[end-1]){
        end--;
    }//从末尾开始找第一个递增的 用end来保存
    end--;
    if(end<1)
    return;
    range(end,n);//将end 开始到n的重新开始0排列 
}

void output(int n)
{
    for(int i=1;i<=n;i++)
    printf("%c",str[order[i]]);
    Order(n);
}

int main(){
    int n;
    scanf("%s",str+1);
    n=strlen(str+1);
    Initorder();
    for(int i=1;i<=n;i++)
        for(int j=i;j<=n;j++)
        {
            if(str[i]>str[j])
            {
                int tem;
                tem=str[i];
                str[i]=str[j];
                str[j]=tem;
            }
        }
    //按照字典序排列
    int time=1;
    for(int i=1;i<=n;i++)
    time*=i;
    while(time)
    {
        output(n);
        if(time-1)
        printf("\n");
        time--;
    }
    system("pause");
}

平时做题没有写注释的习惯 回头看起来真的累 所以就在blog里整理一下了 希望能够有对别人也有所帮助 我只是一个新手 如果有更好的优化也欢迎交流

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值