一道字符数组的全排序问题

今天和一个同学在听宣讲会回来的路上谈起她之前笔试的时候的一道问题,是字符数组的全排序问题,具体是列出一个字符数组里的字符的全排序,例如输入abc,则打印出来的是abc、acb、bac、bca、cab、cba。

这是一道排列组合的问题,同学的想法是这样的,可以使用递归的方式,每次把数组对半分,然后分别求全排列,返回全排列的值,递归终止条件是数组元素只有一个,但是这种方式我在纸上算了一下,比如说abc,对半分,一半是ab,一半是c,然后对ab再对半分,分为a和b,此时a无法对半分应该返回a,然后b返回b,则ab应该返回的是ab和bc,然后c那边返回的是c,这时候再对(ab、ba)和c分别求全排列,得到了abc,bac,cab,cba。这种方式少了两个组合。感觉不对,或者是我误解了同学的意思。

我是这样想的,这是一道排列组合的问题,我们可以第一次取出三个字符里的一个,有三种取法,第二次取剩余的两个元素中的一个,有两种取法,第三次取最后一个,只有一种取法,因此计算出来是3*2*1 = 6 种排列。可以使用递归的方法来实现,下面这张图片具体给出了递归的过程:

(图片来自:http://www.cnblogs.com/GoAhead/archive/2012/05/30/2526563.html)

一道字符数组的全排序问题_第1张图片


具体我的实现方式是,使用一个递归函数sort(String s,String prefix),传入两个参数,一个是剩余的字符串,还有一个是之前的字符串的组合,如果剩余的字符串只有一个字符,那么输出prefix+s,例如说,第一次传入的是abc和“”,那么进行for循环遍历abc,第一次是a,则先取出a,然后和剩余字符串作为参数的递归调用sort("bc",a)。同理,第二次是b...直到剩下最后一个元素为止。

代码实现我想到用可变长字符串StringBuffer,可能有点鸡肋,因为后面去翻了一下java面试宝典,它的代码更精炼,但是也是使用递归方式,我的代码如下:

/*	程序来源:日本某著名软件公司
 * 	源文件名称:TestAllSort.java
 *	要  点:
 *		输入一个字符串,打印出该字符串中字符的所有排列。
 *		字符包括大小写字母
 *		例如:输入字符串abc,则输出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。
 */

public class TestAllSort{

	public static void main(String[] args){
		sort("abc","");
	}
	
	public static void sort(String s,String prefix){
		StringBuffer sb = new StringBuffer(s);
		
		if(sb.length() == 1)
			System.out.println(prefix+sb.charAt(0));
		else
			for(int i=0;i
输出如下:
一道字符数组的全排序问题_第2张图片

在Java程序员面试宝典中使用的是LinkedList,具体的算法也是差不多,但是代码更加精炼:

/*	程序来源:日本某著名软件公司(代码来自java程序员面试宝典)
 * 	源文件名称:TestAllSort2.java
 *	要  点:
 *		输入一个字符串,打印出该字符串中字符的所有排列。
 *		字符包括大小写字母
 *		例如:输入字符串abc,则输出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。
 */
 import java.util.*;
 
 public class TestAllSort2{
	public static void main(String[] args){
		String[] array = new String[]{
			"1","2","3","4"
		};
		
		listAll(Arrays.asList(array),"");
	}
	
	public static void listAll(List candidate,String prefix){
		if(candidate.isEmpty()){
			System.out.println(prefix);
		}
		
		for(int i = 0;i

总结,无论用何种方式,使用递归是比较简单的。但是毕竟效率不高,按照同学来说,如果是100个字符,就会产生100!个结果,在运算过程中可能会造成内存溢出。


你可能感兴趣的:(笔试试题,java)