题目描述:
 
   给定一个由不同的小写字母组成的字符串,输出这个字符串的所有全排列。
 
   我们假设对于小写字母有'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
 
   提示:
 
   每组样例输出结束后要再输出一个回车。
 
   想必大家对perm递归算法求全排列并不陌生,但我贴出来的题目却不能用perm算法来解决,为什么呢?请容我慢慢道来,首先题目对全排列有着非常严格的顺序要求,即按字典顺序排列,就是这个perm算法是满足不了的(或许经过小小的改变是可以实现的,我们在这里就不讨论了)。那么下来我来谈谈perm算法的核心思:举个例子,比如要你1的全排列,你肯定会说那还不简单啊,那么接下来加深难度求1,2的全排列,其实也不难,现在让你求1,2,3,4,5的全排列呢,还转得过来吗?现在我们可以这样想,3,4,5的全排列是以3开头的4,5的全排列组合和4开头的3,5的全排列组合以及以5开头的3,4全排列组合。这就是perm算法的核心思想,列出一个通俗一点的式子 www.jamo123.com
 
   从而可以推断,设一组数p = {r1, r2, r3, … ,rn}, 全排列为perm(p),pn = p - {rn}.
 
   因此perm(p) = r1perm(p1), r2perm(p2), r3perm(p3), … , rnperm(pn)。
 
   当n = 1时perm(p} = r1.
 
   下面贴出代码:
 
   #include<CSTDIO>
 
   #include<CSTRING>
 
   #define MAX 10
 
   using namespace std;
 
   void swap(char str[],int i,int j)
 
   {
 
   int temp;
 
   temp=str[i];
 
   str[i]=str[j];
 
   str[j]=temp;
 
   }
 
   void perm(char str[],int k,int m)
 
   {
 
   int i;
 
   if(k>m)
 
   {
 
   for(i=0;i<=m;i++)
 
   printf("%c",str[i]);
 
   printf("\n");
 
   }
 
   else
 
   {
 
   for(i=k;i<=m;i++)
 
   {
 
   swap(str,k,i);
 
   perm(str,k+1,m);
 
   swap(str,k,i);
 
   }
 
   }
 
   }
 
   int main(int argc,char *argv[])
 
   {
 
   char str[MAX];
 
   while(scanf("%s",str)!=EOF)
 
   {
 
   int len=strlen(str);
 
   perm(str,0,len-1);
 
   printf("\n");
 
   }
 
   return 0;
 
   }
 
   这里会出现两个问题,其一是超时,其二是答案顺序不对…
 
   因为每次都进行的是将数组中的数与第一个数进行交换,它注重的是所有的全排列,但没有注意到换位顺序的问题,这样会产生一个问题:比如 1 2 3 4 的全排列,处理2,3,4的全排列时会将4与2交换,这样会出现1432排在1423的前面。所以如果对全排列的顺序有非常严格的顺序,就不能用perm算法。
 
   例如,abc的全排列:
 
   有序全排: perm全排:
 
   abc abc
 
   acb acb
 
   bac bac
 
   bca bca
 
   cab cba
 
   cba cab
 
   接下来,我们来看一看perm算法的另一大问题,如果对有重复元素的序列进行全排呢?例如:输入122则会输出什么呢?很遗憾,输出结果为:122,122,212,221,221,212(如果你能直接说出来,那么你对perm算法的运行流程就弄明白了),这样的结果明显是不对的,该如何解决呢?我们来看一下,第1个数与第2个数交换得到212(此时第一个数在第二个位置),接着第3个数与第2个数交换得到221(此时第一个数1在第三个位置上,第三个数在第二个位置上,第二个数在第一个位置上),然而第二个数与第三个数是相等的(原序列上),这不相当于直接第三个数与第一个数交换了吗?一下子把下面的事给做了。所以第i个数与第j个数交换时,要求[i,j)中没有与第j个数相等的数就行了托福答案 www.yztrans.com
 
   代码:
 
   #include<CSTDIO>
 
   #include<CSTRING>
 
   #define MAX 10
 
   using namespace std;
 
   void swap(char str[],int i,int j)
 
   {
 
   int temp;
 
   temp=str[i];
 
   str[i]=str[j];
 
   str[j]=temp;
 
   }
 
   bool IsUnique(char str[],int start,int end)//检查重复项
 
   {
 
   int i;
 
   for(i=start;i<END;I++) if(k i; int { m) k,int str[],int perm(char void } true; return false; if(str[i]="=str[end])">m)
 
   {
 
   for(i=0;i<=m;i++)
 
   printf("%c",str[i]);
 
   printf("\n");
 
   }
 
   else
 
   {
 
   for(i=k;i<=m;i++)
 
   {
 
   if(IsUnique(str,k,i))
 
   {
 
   swap(str,k,i);
 
   perm(str,k+1,m);
 
   swap(str,k,i);
 
   }
 
   }
 
   }
 
   }
 
   int main(int argc,char *argv[])
 
   {
 
   char str[MAX];
 
   while(scanf("%s",str)!=EOF)
 
   {
 
   int len=strlen(str);
 
   perm(str,0,len-1);
 
   printf("\n");
 
   }
 
   return 0;
 
   }

全排列算法之Perm算法实现的更多相关文章

  1. 算法:KMP算法

    算法:KMP排序 算法分析 KMP算法是一种快速的模式匹配算法.KMP是三位大师:D.E.Knuth.J.H.Morris和V.R.Pratt同时发现的,所以取首字母组成KMP. 少部分图片来自孤~影 ...

  2. BF算法与KMP算法

    BF(Brute Force)算法是普通的模式匹配算法,BF算法的思想就是将目标串S的第一个字符与模式串T的第一个字符进行匹配,若相等,则继续比较S的第二个字符和 T的第二个字符:若不相等,则比较S的 ...

  3. Levenshtein Distance算法(编辑距离算法)

    编辑距离 编辑距离(Edit Distance),又称Levenshtein距离,是指两个字串之间,由一个转成另一个所需的最少编辑操作次数.许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符, ...

  4. javascript数据结构与算法--高级排序算法

    javascript数据结构与算法--高级排序算法 高级排序算法是处理大型数据集的最高效排序算法,它是处理的数据集可以达到上百万个元素,而不仅仅是几百个或者几千个.现在我们来学习下2种高级排序算法-- ...

  5. ISAP算法对 Dinic算法的改进

    ISAP算法对 Dinic算法的改进: 在刘汝佳图论的开头引言里面,就指出了,算法的本身细节优化,是比较复杂的,这些高质量的图论算法是无数优秀算法设计师的智慧结晶. 如果一时半会理解不清楚,也是正常的 ...

  6. 文本比较算法Ⅱ——Needleman/Wunsch算法

    在"文本比较算法Ⅰ--LD算法"中介绍了基于编辑距离的文本比较算法--LD算法. 本文介绍基于最长公共子串的文本比较算法--Needleman/Wunsch算法. 还是以实例说明: ...

  7. 文本比较算法三——SUNDAY 算法

    SUNDAY 算法描述: 字符串查找算法中,最著名的两个是KMP算法(Knuth-Morris-Pratt)和BM算法(Boyer-Moore).两个算法在最坏情况下均具有线性的查找时间.但是在实用上 ...

  8. [算法]检测空间三角形相交算法(Devillers & Guigue算法)

    #pragma once //GYDevillersTriangle.h /* 快速检测空间三角形相交算法的代码实现(Devillers & Guigue算法) 博客原地址:http://bl ...

  9. 最短路径算法之Dijkstra算法(java实现)

    前言 Dijkstra算法是最短路径算法中为人熟知的一种,是单起点全路径算法.该算法被称为是“贪心算法”的成功典范.本文接下来将尝试以最通俗的语言来介绍这个伟大的算法,并赋予java实现代码. 一.知 ...

随机推荐

  1. 【模拟】XMU 1062 山东煎饼

    题目链接: http://acm.xmu.edu.cn/JudgeOnline/problem.php?id=1062 题目大意: 已知金钱,和各面额钞票张数,问最少可以换成几张. 题目思路: [模拟 ...

  2. URL图片预览(createObjectURL)

    1.说明 1)createObjectURL 作用:创建url(creates  a URL for the specified object); 语法:var url = URL.createObj ...

  3. 乱译文档--Musca介绍

    胡乱翻译的,信,达,雅只能到达的水平.发现错误的话望留言好修改. 原文地址:http://aerosuidae.net/musca.html aerosuidae.net Musca 果蝇 A sim ...

  4. G - Strongly connected - hdu 4635(求连通分量)

    题意:给你一个图,问最多能添加多少条边使图仍为不是强连通图,如果原图是强连通输出 ‘-1’ 分析:先把求出连通分量进行缩点,因为是求最多的添加边,所以可以看成两部分 x,y,只能一部分向另外一部分连边 ...

  5. C++编写ATM(1)

    // ATM的初始.cpp : 定义控制台应用程序的入口点. // /************************************************* 运行环境: VS2008 作者 ...

  6. foreach as 和 in_array

    1.$arr = array("one", "two", "three"); foreach ($arr as $value) { echo ...

  7. OpenSSL与公钥私钥证书签名的千丝万缕

    导语 人对任何事物的认识都是阶段性的,从无知到知晓,从懵懂到半知半解,从误解到将信将疑,从晕头转向到下定决心吃透. 介绍 OpenSSL是一个强大的命令行工具,它可以用来处理许多种跟PKI(Publi ...

  8. Linux shell 之 提取文件名和目录名的一些方法

    很多时候在使用Linux的shell时,我们都需要对文件名或目录名进行处理,通常的操作是由路径中提取出文件名,从路径中提取出目录名,提取文件后缀名等等.例如,从路径/dir1/dir2/file.tx ...

  9. Java虚拟机内存区域堆(heap)的管理

    在上一节中Java 出现内存溢出的定位以及解决方案 中对于Java虚拟机栈以及方法区的内存出现的异常以及处理方式进行了解析,由于Java虚拟机对于堆的管理十分复杂,并且Java虚拟机中最基本的内存区域 ...

  10. How to configure Gzip for JBoss?---refer

    Question: I think to try to speed up my Web App by reducing the size of transferred data. For exampl ...