java实现全排列输出
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实现全排列输出的更多相关文章
- n全排列输出和 n个数的组合(数字范围a~b)
n全排列输出: int WPermutation(int num, bool bRepeat) num表示num全排列 bRepeat标志是否产生重复元素的序列. int Permutation(in ...
- JAVA中集合输出的四种方式
在JAVA中Collection输出有四种方式,分别如下: 一) Iterator输出. 该方式适用于Collection的所有子类. public class Hello { public stat ...
- Java数字格式化输出时前面补0
Java数字格式化输出时前面补0 星期日 2014年11月30日| 分类: Java /** * 里数字转字符串前面自动补0的实现. * */ public class TestString ...
- Java自定义日志输出文件
Java自定义日志输出文件 日志的打印,在程序中是必不可少的,如果需要将不同的日志打印到不同的地方,则需要定义不同的Appender,然后定义每一个Appender的日志级别.打印形式和日志的输出路径 ...
- Java中直接输出一个类的对象
例如 package com.atguigu.java.fanshe; public class Person { String name; private int age; public Strin ...
- 【JAVA零基础入门系列】Day7 Java输入与输出
[JAVA零基础入门系列](已完结)导航目录 Day1 开发环境搭建 Day2 Java集成开发环境IDEA Day3 Java基本数据类型 Day4 变量与常量 Day5 Java中的运算符 Day ...
- Java中如何输出对勾,ASCII编码与字符串相互转换
Java中如何输出对勾? 最简单的方法是,从那个地方拷贝一个对勾的字符,然后System.out.println("√"); 但是心里总会担心,万一机器不认这个字符该怎么办?(可能 ...
- Java-Runoob-高级教程-实例-数组:05. Java 实例 – 数组输出
ylbtech-Java-Runoob-高级教程-实例-数组:05. Java 实例 – 数组输出 1.返回顶部 1. Java 实例 - 数组输出 Java 实例 以下实例演示了如何通过循环输出数 ...
- JS实现的数组全排列输出算法
本文实例讲述了JS实现的数组全排列输出算法.分享给大家供大家参考.具体分析如下: 这段js代码对数组进行全排列输出,改进了一些老的代码 从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来, ...
随机推荐
- linux服务器安装svn超详细介绍
#!/bin/sh REPOS="$1" REV="$2" export LANG=en_US.UTF-8 LOG_PATH=/tmp/svn.log echo ...
- Qt 入门 ---- 如何在程序窗口显示图片?
步骤: 1. 选择资源(准备图片) 2. 加载资源(导入图片) 3. 使用资源(显示图片) 具体操作流程: ① 从网上寻找合适的图片素材,下载到本地,在项目根目录下创建一个images文件夹存储程序中 ...
- ThinkPHP5 SQL注入漏洞 && 敏感信息泄露
访问看到用户名被显示了 http://192.168.49.2/index.php?ids[]=1&ids[]=2 访问http://your-ip/index.php?ids[0,updat ...
- 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 ...
- 配置 Nvidia GPU 主机的运行环境
在 Linux 主机上配置了很多次 Cuda/CuDNN 的运行环境,在此记录下用到的脚本命令以复用. 特别提醒,先了解清楚 GPU 卡的型号,查清与主机 Linux 内核兼容的驱动程序.Cuda 和 ...
- SpringBoot数据访问之Druid启动器的使用
数据访问之Druid启动器的使用 承接上文:SpringBoot数据访问之Druid数据源的自定义使用 官方文档: Druid Spring Boot Starter 首先在在 Spring Boot ...
- 字节跳动前技术总监开源分享《Android架构设计权威指南》,YYDS!
架构就像是一场进化史,根据不同时期的需求,演变出不同的架构,车轮滚滚,到今天,移动端框架百花齐放,让人目不暇接.但是其中的本质是磨灭不了的,换言之根本没有磨灭而是隐藏到了人们所看不到的地方,但是依旧发 ...
- [C++]-unordered_map 映射
unordered_map和map的区别请点击这里. 本文中的代码跟[C++]-map 映射中的代码仅仅是把定义的map类型数据定义成了unordered_map类型数据. 代码 #include&l ...
- 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 ...
- docker容器dockerfile详解
docker公司在容器技术发展中提出了镜像分层的理念,可以说也是这个革命性的理念让原本只不过是整合linux内核特性的容器,开始野蛮生长. docker通过UnionFS联合文件系统将镜像的分层实现合 ...