一道字符数组的全排序问题
2014-04-18 23:01
253 查看
今天和一个同学在听宣讲会回来的路上谈起她之前笔试的时候的一道问题,是字符数组的全排序问题,具体是列出一个字符数组里的字符的全排序,例如输入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)
![](https://img-blog.csdn.net/20140418221256750?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvejQyMTc0NTk2Mw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
具体我的实现方式是,使用一个递归函数sort(String s,String prefix),传入两个参数,一个是剩余的字符串,还有一个是之前的字符串的组合,如果剩余的字符串只有一个字符,那么输出prefix+s,例如说,第一次传入的是abc和“”,那么进行for循环遍历abc,第一次是a,则先取出a,然后和剩余字符串作为参数的递归调用sort("bc",a)。同理,第二次是b...直到剩下最后一个元素为止。
代码实现我想到用可变长字符串StringBuffer,可能有点鸡肋,因为后面去翻了一下java面试宝典,它的代码更精炼,但是也是使用递归方式,我的代码如下:
![](https://img-blog.csdn.net/20140418222351765?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvejQyMTc0NTk2Mw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
在Java程序员面试宝典中使用的是LinkedList,具体的算法也是差不多,但是代码更加精炼:
总结,无论用何种方式,使用递归是比较简单的。但是毕竟效率不高,按照同学来说,如果是100个字符,就会产生100!个结果,在运算过程中可能会造成内存溢出。
这是一道排列组合的问题,同学的想法是这样的,可以使用递归的方式,每次把数组对半分,然后分别求全排列,返回全排列的值,递归终止条件是数组元素只有一个,但是这种方式我在纸上算了一下,比如说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)
具体我的实现方式是,使用一个递归函数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<sb.length();i++){ char temp = sb.charAt(i); sort(sb.deleteCharAt(i).toString(),prefix+temp); sb.insert(i,temp); } } }输出如下:
在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<candidate.size();i++){ List temp = new LinkedList(candidate); listAll(temp,prefix+temp.remove(i)); } } }
总结,无论用何种方式,使用递归是比较简单的。但是毕竟效率不高,按照同学来说,如果是100个字符,就会产生100!个结果,在运算过程中可能会造成内存溢出。
相关文章推荐
- 一道经典面试题,字符数组排序问题(字符包含a-z、A-Z、0-9.)
- 关于动态存储分配函数的调用,在已经过排序的数组中查找及删除内容的操作,余数的分析,删除字符数组中的空格,对链表的逆置,在源字符串中查找子字符串的个数,函数指针以及函数的调用,循环赋值带来的问题以及插入
- 使用qsort对二维字符数组排序疑难问题调试及解决过程
- 给定一个字符数组,求由这些字符组成的所有不同的排序问题.
- 一道数组排序问题
- C语言将数组中元素的数排序输出的相关问题解决
- 算法1:寻找字符串数组中指定字符出现的字符串并排序
- 华为:现有一串字符串,请对字符串中的数字字符按照升序排序,其他非数字字符存储位置保持不变,将结果保存至output数组中
- 第一周第四天([大小写变换问题][判断是否为email][求对角线的值] [生成数组][数字中添加逗号][生成10个两位随机数,然后再进行排序] [复制数组||将指定数组的指定范围复制到新的数组])
- 对二维字符数组排序(2sort和1qsort)
- 关于长字符数组strcpy到短字符数组发生的问题
- 数组排序问题
- sort对二维字符数组排序
- 字符串数组排序问题
- c中字符数组的问题
- JPasswordField 中得到的字符数组转化为字符串(密码乱码问题)
- 字符数组输出的问题
- 第二十六讲项目3.1(2)字符数组排序使其能对字符数组进行排序
- 百练_2752:字符串数组排序问题
- 第十三周 项目四--数组的排序(2)对字符排序