java实现全排列输出

转自:http://easonfans.iteye.com/blog/517286

最近在找工作,面试java程序员或者软件工程师,在笔试的时候常常见到这么一道题:全排列 的输出数组(常常要求是整数),其实这道题不难,主要是递归调用,在baidu或者google上已经有很多人提出了解法,但是大部分可读性很差,让我们 莘莘学子根本就记不住。我来简单的说一下:

其实这个问题的解法基本思路是这样的:递归

但是我们在使用递归的时候要注意结束条件,也就是递归到最后,要推出递归方法,目前网上的主要思路如下:

  1. 1 public 递归方法(参数列表){
  2. 2 if(列表的元素只有两个){
  3. 3 输出:“元素一元素二”
  4. 4 输出:“元素二元素一”
  5. 5 }else{
  6. 6 //此时元素有两个以上,这时候要使用递归
  7. 7 递归方法(参数列表)//使用递归方法将元素细分
  8. 8 }
  9. 9 }

我这个思路是在百度上看到的,但是具体链接和源代码我再没找到,因为那个代码很乱……Sorry!

我在Eclipse实现了这个思路,代码如下:

  1. 1 import java.util.LinkedList;
  2. 2 import java.util.List;
  3. 3
  4. 4
  5. 5 public class ListAllPrint {
  6. 6 /**
  7. 7 * 使用createList方法,填充参数列表传递过来的List,默认是Integer,一般是这个类型,你可以修改别的类型
  8. 8 */
  9. 9 public void createList(int n,List list){
  10. 10 if(n==0){//当是n=0是,默认就是3了
  11. 11 n=3;
  12. 12 }
  13. 13 for(int i=1;i<=n;i++){//for循环填充list
  14. 14 list.add(i);
  15. 15 }
  16. 16 }
  17. 17 /**
  18. 18 * printAll是输出全排列的递归调用方法,list是传入的list,用LinkedList实现,而prefix用于转载以及输出的数据
  19. 19 */
  20. 20 public void printAll(List candidate, String prefix){
  21. 21 if(candidate.size()==1){
  22. 22 //一个元素时候,输出……;不过这个实现,这个if传递不到递归中,仅仅是测试代码中list的size为1时调用一次
  23. 23 System.out.println(candidate.get(0));
  24. 24 }
  25. 25 if(candidate.size()==2){
  26. 26 //输出两个元素时候,颠倒顺序
  27. 27 System.out.println(prefix+candidate.get(0)+candidate.get(1));
  28. 28 System.out.println(prefix+candidate.get(1)+candidate.get(0));
  29. 29 }else{
  30. 30 for (int i = 0; i < candidate.size(); i++) {
  31. 31 List temp = new LinkedList(candidate);
  32. 32 printAll(temp, prefix + temp.remove(i));//递归调用
  33. 33 }
  34. 34 }
  35. 35 }
  36. 36
  37. 37 /**
  38. 38 * 测试代码
  39. 39 */
  40. 40 public static void main(String[] args) {
  41. 41 // TODO Auto-generated method stub
  42. 42 LinkedList<Integer> list=new LinkedList<Integer>();
  43. 43 ListAllPrint lap=new ListAllPrint();
  44. 44 lap.createList(3, list);
  45. 45 lap.printAll(list,"");
  46. 46 }
  47. 47 }

我在编写这个程序的时候,发现自己要写一个:

  1. 1 if(candidate.size()==1){
  2. 2 //一个元素时候,输出……;不过这个实现,这个if传递不到递归中,仅仅是测试代码中list的size为1时调用一次
  3. 3 System.out.println(candidate.get(0));
  4. 4 }

语句,用来当list初始就为size就为1时使用。我觉得这个效率很差,不仅每次递归也判断,而且不符合递归的思想:递归到最后应该是一个元素(查找算法递归实现最后是一个元素的判断)

所以,我又添加了一个参数在递归的方法中,用来记录原list的长度,使得每次的排列字符串输出可以完全记载到第二个参数prefix,不使用2,而是使用length来判断是否加最后一个元素入prefix,从而结束输出,从而使代码显得漂亮多了。修改如下:

  1. 1 import java.util.ArrayList;
  2. 2 import java.util.LinkedList;
  3. 3 import java.util.List;
  4. 4
  5. 5
  6. 6 public class ListAllPrint2 {
  7. 7 /**
  8. 8 * 使用createList方法,填充参数列表传递过来的List,默认是Integer,一般是这个类型,你可以修改别的类型
  9. 9 */
  10. 10 public void createList(int n,List list){
  11. 11 if(n==0){
  12. 12 n=3;
  13. 13 }
  14. 14 for(int i=1;i<=n;i++){
  15. 15 list.add(i);
  16. 16 }
  17. 17 }
  18. 18 /**
  19. 19 * printAll是输出全排列的递归调用方法,list是传入的list,用LinkedList实现,
  20. 20 * 而prefix用于转载以及输出的数据
  21. 21 * length用于记载初始list的长度,用于判断程序结束。
  22. 22 */
  23. 23 public void printAll(List candidate, String prefix,int length){
  24. 24 if(prefix.length()==length)
  25. 25 System.out.println(prefix);
  26. 26 for (int i = 0; i < candidate.size(); i++) {
  27. 27 List temp = new LinkedList(candidate);
  28. 28 printAll(temp, prefix + temp.remove(i),length);
  29. 29 }
  30. 30 }
  31. 31
  32. 32 /**
  33. 33 * 测试代码
  34. 34 */
  35. 35 public static void main(String[] args) {
  36. 36 // TODO Auto-generated method stub
  37. 37 ArrayList<Integer> list=new ArrayList<Integer>();
  38. 38 ListAllPrint2 lap=new ListAllPrint2();
  39. 39 lap.createList(3, list);
  40. 40 lap.printAll(list,"",list.size());
  41. 41 }
  42. 42 }

这样子看上去漂亮多了!

呵呵,相关的project文件如下,这两个class都在一个项目下:

希望能对大家有所帮助!

java实现全排列输出的更多相关文章

  1. n全排列输出和 n个数的组合(数字范围a~b)

    n全排列输出: int WPermutation(int num, bool bRepeat) num表示num全排列 bRepeat标志是否产生重复元素的序列. int Permutation(in ...

  2. JAVA中集合输出的四种方式

    在JAVA中Collection输出有四种方式,分别如下: 一) Iterator输出. 该方式适用于Collection的所有子类. public class Hello { public stat ...

  3. Java数字格式化输出时前面补0

    Java数字格式化输出时前面补0 星期日 2014年11月30日|  分类: Java     /** * 里数字转字符串前面自动补0的实现. * */ public class TestString ...

  4. Java自定义日志输出文件

    Java自定义日志输出文件 日志的打印,在程序中是必不可少的,如果需要将不同的日志打印到不同的地方,则需要定义不同的Appender,然后定义每一个Appender的日志级别.打印形式和日志的输出路径 ...

  5. Java中直接输出一个类的对象

    例如 package com.atguigu.java.fanshe; public class Person { String name; private int age; public Strin ...

  6. 【JAVA零基础入门系列】Day7 Java输入与输出

    [JAVA零基础入门系列](已完结)导航目录 Day1 开发环境搭建 Day2 Java集成开发环境IDEA Day3 Java基本数据类型 Day4 变量与常量 Day5 Java中的运算符 Day ...

  7. Java中如何输出对勾,ASCII编码与字符串相互转换

    Java中如何输出对勾? 最简单的方法是,从那个地方拷贝一个对勾的字符,然后System.out.println("√"); 但是心里总会担心,万一机器不认这个字符该怎么办?(可能 ...

  8. Java-Runoob-高级教程-实例-数组:05. Java 实例 – 数组输出

    ylbtech-Java-Runoob-高级教程-实例-数组:05. Java 实例 – 数组输出 1.返回顶部 1. Java 实例 - 数组输出  Java 实例 以下实例演示了如何通过循环输出数 ...

  9. JS实现的数组全排列输出算法

    本文实例讲述了JS实现的数组全排列输出算法.分享给大家供大家参考.具体分析如下: 这段js代码对数组进行全排列输出,改进了一些老的代码 从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来, ...

随机推荐

  1. linux服务器安装svn超详细介绍

    #!/bin/sh REPOS="$1" REV="$2" export LANG=en_US.UTF-8 LOG_PATH=/tmp/svn.log echo ...

  2. Qt 入门 ---- 如何在程序窗口显示图片?

    步骤: 1. 选择资源(准备图片) 2. 加载资源(导入图片) 3. 使用资源(显示图片) 具体操作流程: ① 从网上寻找合适的图片素材,下载到本地,在项目根目录下创建一个images文件夹存储程序中 ...

  3. ThinkPHP5 SQL注入漏洞 && 敏感信息泄露

    访问看到用户名被显示了 http://192.168.49.2/index.php?ids[]=1&ids[]=2 访问http://your-ip/index.php?ids[0,updat ...

  4. ffmpeg 任意文件读取漏洞/SSRF漏洞 (CVE-2016-1897/CVE-2016-1898)

    影响版本 在FFMpeg2.X poc http://192.168.49.2:8000/?name={%25%20for%20c%20in%20[].__class__.__base__.__sub ...

  5. 配置 Nvidia GPU 主机的运行环境

    在 Linux 主机上配置了很多次 Cuda/CuDNN 的运行环境,在此记录下用到的脚本命令以复用. 特别提醒,先了解清楚 GPU 卡的型号,查清与主机 Linux 内核兼容的驱动程序.Cuda 和 ...

  6. SpringBoot数据访问之Druid启动器的使用

    数据访问之Druid启动器的使用 承接上文:SpringBoot数据访问之Druid数据源的自定义使用 官方文档: Druid Spring Boot Starter 首先在在 Spring Boot ...

  7. 字节跳动前技术总监开源分享《Android架构设计权威指南》,YYDS!

    架构就像是一场进化史,根据不同时期的需求,演变出不同的架构,车轮滚滚,到今天,移动端框架百花齐放,让人目不暇接.但是其中的本质是磨灭不了的,换言之根本没有磨灭而是隐藏到了人们所看不到的地方,但是依旧发 ...

  8. [C++]-unordered_map 映射

    unordered_map和map的区别请点击这里. 本文中的代码跟[C++]-map 映射中的代码仅仅是把定义的map类型数据定义成了unordered_map类型数据. 代码 #include&l ...

  9. Convert a Private Project on bitbucket.com to a github Public Project

    Create a public repo on github, you can add README or License files on the master branch, suppose th ...

  10. docker容器dockerfile详解

    docker公司在容器技术发展中提出了镜像分层的理念,可以说也是这个革命性的理念让原本只不过是整合linux内核特性的容器,开始野蛮生长. docker通过UnionFS联合文件系统将镜像的分层实现合 ...