zoukankan      html  css  js  c++  java
  • ybt1199 全排列

    ybt1199 全排列

    【题目描述】

    给定一个由不同的小写字母组成的字符串,输出这个字符串的所有全排列。

    我们假设对于小写字母有‘a’ <‘b’ < ... <‘y’<‘z’,而且给定的字符串中的字母已经按照从小到大的顺序排列。

    【输入】

    只有一行,是一个由不同的小写字母组成的字符串,已知字符串的长度在1到6之间。

    【输出】

    输出这个字符串的所有排列方式,每行一个排列。要求字母序比较小的排列在前面。字母序如下定义:

    已知S=s1s2...sk,T=t1t2...tk,则S<T等价于,存在p(1≤p≤k),使得s1=t1,s2=t2,...,sp−1=tp−1,sp<tp成立。

    【输入样例】

    abc
    

    【输出样例】

    abc acb bac bca cab cba
    

    【题解】

    由于原数组使用字典序排列的,所以就不需要再次排序。

    我们小学就学过全排列的基本思路:在确定首位的基础上,全排列其余位,然后依次更换首位,使所有元素在首位出现一遍,这样这一层递归就结束了。

    这是一个典型的递归模型,在确定第x位的基础上,全排列x+1位及其后面的元素。所以递归函数就要分两部分:枚举第x位和全排列后面的位。

    递归边界就是x=l(x是最后一位后面的一位)时,已经将第x位前面的元素(所有元素)的位置确定了下来,只要输出就好了。

    实现这个算法,需要保证一个元素的位置确定后,不会出现第二次,这时,就要在确定a[i]成为b[x]的元素之前,走一遍b数组,查找是否有a[i]在b中出现过。若出现过,就找下一个符合条件的a[i]判断是否可以。

    这样就可以写出递归函数:

    void f(int x) {//x是当前数组b的长度,由于b是从0开始命名的,所以x也可以做本次操作的b的当前位的指针
        if(x==l) {//递归边界,本次结束了,输出结果
            for(int i=0; i<l; ++i)
                cout<<b[i];
            cout<<endl;
        }
        else {//没有结束,将b[x]的位置确定下来
            bool bj=0;//判断a[i]是否在b中出现过将要使用的标记
            char t;
            for(int i=0; i<l; ++i) {//枚举第x位是a[i]
                t=a[i];//提取a[i]并暂存
                bj=0;
                for(int j = 0; j < x; ++j) {//扫一遍b数组,判断a[i]是否在已排列的数组中出现
                    if(b[j]==t) {//已排列的数组中有a[i]
                        bj=1;//打标记
                        break;//跳出(已经找到了,再找下去也不会找到a[i]了,因为字符串不重复)
                    }
                }
                if(bj)//b[j]就是之前出现过的a[i],所以再找下一个a[i]放入b
                    continue;
                else {
                b[x] = a[i];//这是a[i]没有出现的情况,就把a[i]放到b[j+1]中。
                f(x+1);//在确定前x位的基础上,全排列x+1位以及后面的元素
                }
            }
        }
    }
    

    由于n个不重复元素的全排列有n!个,所以算法的复杂度可以达到n^n^,但是因为本题数据范围是1<=n<=6,所以这样暴力的复杂度完全没问题,接下来是完整代码:

    #include<iostream>
    #include<cstring>
    using namespace std;
    string a,b;
    int l;
    void f(int x)
    int main() {
        cin>>a;
        l=a.length();
        f(0);
        return 0;
    }
    

    感谢题解的思路帮助。

    除夕快乐!

  • 相关阅读:
    1.ok6410移植bootloader,移植u-boot,学习u-boot命令
    ok6410按键中断编程,linux按键裸机
    四. jenkins部署springboot项目(1)--window环境
    一.jenkins安装(windows环境)
    oracle服务端导出/导入方式expdp/impdp
    linux 日志文件查看
    linux kafka进程挂了 自动重启
    kafka manager遇到的一些问题
    if条件语句
    shell脚本的条件测试与比较
  • 原文地址:https://www.cnblogs.com/Wild-Donkey/p/12232054.html
Copyright © 2011-2022 走看看