问题:给出一个字符串,输出所有可能的排列。

全排列有多种算法,此处仅介绍常用的两种:字典序法和递归法。

1、字典序法:

如何计算字符串的下一个排列了?来考虑"926520"这个字符串,我们从后向前找第一双相邻的递增数字,"20"、"52"都是非递增的,"26 "即满足要求,称前一个数字2为替换数,替换数的下标称为替换点,再从后面找一个比替换数大的最小数(这个数必然存在),0、2都不行,5可以,将5和2交换得到"956220",然后再将替换点后的字符串"6220"颠倒即得到"950226"。

算法概括:从后向前遍历,找出第一个交换点,再按照规则找出第二个交换点,将两者进行交换,对第一个交换点之后的字符进行颠倒操作

  1. package algorithm;
  2.  
  3. import java.util.Arrays;
  4.  
  5. public class DictionaryPermutation {
  6.  
  7. private char[] data;
  8. private int length;
  9.  
  10. public void permutate(String input) {
  11. // change the data type to we needed
  12. changeToData(input);
  13. // sort the data from small to big
  14. Arrays.sort(data);
  15. // output all the order
  16. System.out.println(data);
  17. while (nextPermutate()) {
  18. System.out.println(data);
  19. }
  20. }
  21.  
  22. private void changeToData(String input) {
  23. if (input == null)
  24. return;
  25. data = input.toCharArray();
  26. length = data.length;
  27. }
  28.  
  29. private boolean nextPermutate() {
  30. int end = length - ;
  31. int swapPoint1 = end, swapPoint2 = end;
  32. // the actual swap-point is swapPoint1 - 1
  33. while (swapPoint1 > && data[swapPoint1] <= data[swapPoint1 - ])
  34. swapPoint1--;
  35. if (swapPoint1 == )
  36. return false;
  37. else {
  38. while (swapPoint2 > && data[swapPoint2] <= data[swapPoint1 - ])
  39. swapPoint2--;
  40. swap(data, swapPoint1 - , swapPoint2);
  41. reverse(data, swapPoint1, end);
  42. return true;
  43. }
  44. }
  45.  
  46. private void swap(char[] data, int left, int right) {
  47. char temp = data[left];
  48. data[left] = data[right];
  49. data[right] = temp;
  50. }
  51.  
  52. private void reverse(char[] data, int left, int right) {
  53. for (int i = left, j = right; i < j; i++, j--)
  54. swap(data, i, j);
  55. }
  56.  
  57. public static void main(String... args) {
  58. DictionaryPermutation p = new DictionaryPermutation();
  59. p.permutate("aab");
  60. }
  61.  
  62. }

2、递归法

为方便起见,用123来示例下。123的全排列有123、132、213、231、312、321这六种。首先考虑213和321这二个数是如何得出的。显然这二个都是123中的1与后面两数交换得到的。然后可以将123的第二个数和每三个数交换得到132。同理可以根据213和321来得231和312。因此可以知道——全排列就是从第一个数字起每个数分别与它后面的数字交换。

由于全排列就是从第一个数字起每个数分别与它后面的数字交换。我们先尝试加个这样的判断——如果一个数与后面的数字相同那么这二个数就不交换了。如122,第一个数与后面交换得212、221。然后122中第二数就不用与第三个数交换了,但对212,它第二个数与第三个数是不相同的,交换之后得到221。与由122中第一个数与第三个数交换所得的221重复了。所以这个方法不行。

换种思维,对122,第一个数1与第二个数2交换得到212,然后考虑第一个数1与第三个数2交换,此时由于第三个数等于第二个数,所以第一个数不再与第三个数交换。再考虑212,它的第二个数与第三个数交换可以得到解决221。此时全排列生成完毕。
这样我们也得到了在全排列中去掉重复的规则——去重的全排列就是从第一个数字起每个数分别与它后面非重复出现的数字交换。

(描述从http://blog.csdn.net/hackbuteer1/article/details/6657435处转载)

  1. package algorithm;
  2.  
  3. public class RecursionPermutation {
  4.  
  5. public static void permutate(String input){
  6. if(input == null)
  7. throw new IllegalArgumentException();
  8. char[] data = input.toCharArray();
  9. permutate(data, 0);
  10. }
  11.  
  12. public static void permutate(char[] data, int begin){
  13. int length = data.length;
  14. if(begin == length)
  15. System.out.println(data);
  16. for(int i = begin ; i < length; i++)
  17. {
  18. if(isUnique(data, begin, i)){
  19. swap(data, begin, i);
  20. permutate(data, begin + 1);
  21. swap(data, begin, i);
  22. }
  23. }
  24. }
  25.  
  26. private static boolean isUnique(char[] data, int begin, int end){
  27. for(int i = begin; i < end; i++)
  28. if(data[i] == data[end])
  29. return false;
  30. return true;
  31. }
  32.  
  33. private static void swap(char[] data, int left, int right) {
  34. char temp = data[left];
  35. data[left] = data[right];
  36. data[right] = temp;
  37. }
  38.  
  39. public static void main(String... args){
  40. RecursionPermutation.permutate("aac");
  41. }
  42.  
  43. }

两种常用的全排列算法(java)的更多相关文章

  1. Windows校验文件哈希hash的两种常用方式

    大家经常都到哪儿去下载软件和应用程序呢?有没想过下载回来的软件.应用程序或资源是否安全呢?在 Windows 10 和 Office 2016 发布当初,很多没权限的朋友都使用第三方网站去下载安装映像 ...

  2. Spring Cloud Config采用Git存储时两种常用的配置策略

    由于Spring Cloud Config默认采用了Git存储,相信很多团队在使用Spring Cloud的配置中心时也会采用这样的策略.即便大家都使用了Git存储,可能还有各种不同的配置方式,本文就 ...

  3. 两种常用的jquery事件加载的方法 的区别

    两种常用的jquery事件加载的方法   $(function(){});  window.onload=function(){}  第一个呢,是在DOM结构渲染完成以后调用的,这时候网页中一些资源还 ...

  4. iOS- 网络访问两种常用方式【GET & POST】实现的几个主要步骤

    1.前言 上次,在博客里谈谈了[GET & POST]的区别,这次准备主要是分享一下自己对[GET & POST]的理解和实现的主要步骤. 在这就不多废话了,直接进主题,有什么不足的欢 ...

  5. iOS- 网络请求的两种常用方式【GET & POST】的区别

    GET和POST 网络请求的两种常用方式的实现[GET & POST] –GET的语义是获取指定URL上的资源 –将数据按照variable=value的形式,添加到action所指向的URL ...

  6. IPVS和Nginx两种WRR负载均衡算法详解

    动机 五一临近,四月也接近尾声,五一节乃小长假的最后一天.今天是最后一天工作日,竟然感冒了,半夜里翻来覆去无法安睡,加上窗外大飞机屋里小飞机(也就是蚊子)的骚扰,实在是必须起来做点有意义的事了!    ...

  7. Java中常用到的文件操作那些事(二)——使用POI解析Excel的两种常用方式对比

    最近生产环境有个老项目一直内存报警,不时的还出现内存泄漏,导致需要重启服务器,已经严重影响正常服务了.获取生成dump文件后,使用MAT工具进行分析,发现是其中有个Excel文件上传功能时,经常会导致 ...

  8. js实现两种实用的排序算法——冒泡、快速排序

      分类:js (4443) (0) 零:数据准备,给定数组arr=[2,5,4,1,7,3,8,6,9,0]; 一:冒牌排序 1思想:冒泡排序思想:每一次对比相邻两个数据的大小,小的排在前面,如果前 ...

  9. 说一说Web开发中两种常用的分层架构及其对应的代码模型

    昨天妹子让我帮她解决个问题,本以为可以轻松搞定,但是打开他们项目的一瞬间,我头皮发麻.本身功能不多的一个小项目,解决方案里竟然有几十个类库.仅仅搞明白各个类库的作用,代码层次之间的引用关系就花了一个多 ...

随机推荐

  1. [Swift]LeetCode398. 随机数索引 | Random Pick Index

    Given an array of integers with possible duplicates, randomly output the index of a given target num ...

  2. AES,DES加密JS源文件及其使用方法

    源文件地址:https://github.com/dididi1234/crypto 进入之后直接下载CryptoJS.js,js中直接引用,小程序也一样可以使用 具体使用方法和vue中的Crypto ...

  3. Node.js 多版本安装

    Node.js 多版本安装 Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine(Node.js 是一个基于 ...

  4. PyCharm2019 激活码

    因公司的需求,需要做一个爬取最近上映的电影.列车号.航班号.机场.车站等信息,所以需要我做一个爬虫项目,当然java也可以做爬虫,但是还是没有python这样方便,所以也开始学习Python啦!!! ...

  5. scala查询dataFrame结构

    println(dataFrame.printSchema)

  6. BBS论坛(十三)

    13.1点击更换图形验证码 (1)front/signup.html <div class="form-group"> <div class="inpu ...

  7. PHP 扩展管理

    一直对 PHP 扩展了解的似是而非,每次安装扩展都要百度教程,很容易出现各种错误.所幸整理下管理扩展的所有操作,方便日后操作. 查看已加载的扩展 输出 phpinfo(): 使用 get_loaded ...

  8. C++实现多级排序

    stl中sort详细说明 实现功能:期末开始4位同学的成绩,按多级排序,排序规则为:按数学从小到大,如果数学相等,则按语文从大到小排列,如果语文相等,则按英语从小到大排列,如果英语相等,则按历史从大到 ...

  9. RabbitMQ学习笔记(五) Topic

    更多的问题 Direct Exchange帮助我们解决了分类发布与订阅消息的问题,但是Direct Exchange的问题是,它所使用的routingKey是一个简单字符串,这决定了它只能按照一个条件 ...

  10. SpringBoot基础系列-SpringBoot配置

    原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9990680.html SpringBoot基础系列-SpringBoot配置 概述 属性 ...