java实现全排列输出

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

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

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

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

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

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

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

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

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

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

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

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

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

    一.js文件使用.remove()删除单条数据 在js文件中写updategood函数,在函数中使用.doc()指定要删除的数据id,调用.remove()方法删除数据. 二.wxml文件添加[删除] ...

  2. Gitea 1.4.0 目录穿越导致命令执行漏洞

    复现 POST /vulhub/repo.git/info/lfs/objects HTTP/1.1 Host: 192.168.49.2:3000 Accept-Encoding: gzip, de ...

  3. 论文笔记:(CVPR2017)PointNet: Deep Learning on Point Sets for 3D Classification and Segmentation

    目录 一. 存在的问题 二. 解决的方案 1.点云特征 2.解决方法 三. 网络结构 四. 理论证明 五.实验效果 1.应用 (1)分类: ModelNet40数据集 (2)部件分割:ShapeNet ...

  4. 图文实例解析,InnoDB 存储引擎中行锁的三种算法

    前文提到,对于 InnoDB 来说,随时都可以加锁(关于加锁的 SQL 语句这里就不说了,忘记的小伙伴可以翻一下上篇文章),但是并非随时都可以解锁.具体来说,InnoDB 采用的是两阶段锁定协议(tw ...

  5. OpenGL学习笔记(二)画三角形

    目录 渲染管线(Graphics Pipeline) 编码实现 顶点数据 顶点缓冲对象(VBO) 顶点着色器 编译着色器 片段着色器 着色器程序 链接顶点属性 顶点数组对象 最终绘制三角形 索引缓冲对 ...

  6. 查看Android 系统发送的广播

    命令行输入如下命令 adb shell dumpsys |grep BroadcastRecord

  7. C++ 结构体+数组+取随机数 案例(打印3名老师 带着 5名学生)结构体

    1 //结构体案列 2 3 #include<iostream> 4 #include<string> 5 #include<ctime> 6 using name ...

  8. Redis是不是真的变慢了?

    大家好,今天我们来学习一下如何确定Redis是不是真的变慢了. 我们在使用redis时一定会遇到变慢的时候,那我们如何来判断Redis是否真的变慢了呢, 一个最直接的方法就是查看Redis的响应延迟, ...

  9. [SQL]数据更新

    插入数据 插入单个元组 一般格式: insert into <表名> [<列名1>, <列明2>, --] -- 指出在表中新插入的值的列, values(< ...

  10. CD管理和检索软件比较

    之前一直用EverCD+,考虑到鸡蛋不能放在一个篮子里,又找了几款功能类似的进行了比较,主要考察一下几个功能: 多个镜像:一个数据文件可以包含多个目录的镜像,便于数据管理和搜索: 目录更新:目录内容发 ...