A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 宝安 中级黑马   /  2014-7-23 21:13  /  1842 人查看  /  16 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

前两天走黑马的流程,遇到一道测试题,自己想了两天才弄一个效率超低的,从网上查了一个答案,居然用了四层循环,看的还不太明白,分享下,希望大神能给我指导指导,有什么更好的方法也希望能告诉小弟,谢谢
6、 编程列出一个字符串的全字符组合情况,原始字符串中没有重复字符,例如:
题目:原始字符串是"abc",打印得到下列所有组合情况:
"a" "b" "c"
"ab" "bc" "ca" "ba" "cb" "ac"
"abc" "acb" "bac" "bca" "cab" "cba"
网上答案:
  1. package com.itheima;

  2. import java.util.LinkedList;

  3. public class Test12 {
  4.         static int n=0,count = 0;
  5.         static char[] array = { 'a', 'b','c','d'};
  6.         static LinkedList <char[]> list = new LinkedList<char[]> ();//转化为集合
  7.         static int[] indexs = new int[array.length];
  8.         static int len = array.length;

  9.         /**
  10.          * @param args
  11.          */
  12.         public static void main(String[] args) {
  13.                 // TODO Auto-generated method stub
  14.                 getSub ();
  15.                 for ( char[] cs : list ){
  16.                         System.out.println(cs);
  17.                         }
  18.         }
  19.         private static LinkedList<char[]> getSub ()      //获取
  20.     {
  21.         while (count <= len){
  22.             recursionSub (-1);
  23.             count++;
  24.         }
  25.         return list;
  26.     }
  27.         //
  28.          private static LinkedList <char[]> recursionSub ( int start )
  29.      {
  30.          start++;
  31.          
  32.          if (start > count - 1){
  33.                  return null;
  34.                  }
  35.          for ( indexs[start] = 0; indexs[start] < len; indexs[start]++ ){
  36.                  recursionSub (start);
  37.                  if (start == count - 1){
  38.                          char[] temp = new char[count];
  39.                          for ( int i = count - 1; i >= 0; i-- ){
  40.                                  temp[start - i] = array[indexs[start - i]];
  41.                                  }
  42.                          boolean flag = true;
  43.                          for ( int i = 0; i < temp.length; i++ ){
  44.                                  for ( int j = i+1; j < temp.length; j++ ){
  45.                                          if (temp[i] == temp[j]){
  46.                                                  flag = false;
  47.                                                  break;
  48.                                                  }
  49.                                          }
  50.                                  }
  51.                          if (flag){
  52.                                  list.add (temp);
  53.                                  }
  54.                          }
  55.                  }
  56.          return list;
  57.          }
  58. }
复制代码



16 个回复

倒序浏览
弄个数组,按1个,2个,3个,遍历。
回复 使用道具 举报
HPU--spring87 发表于 2014-7-23 21:21
弄个数组,按1个,2个,3个,遍历。

输入的字符串长度不一定是3,可能是4,5………………10000000000
回复 使用道具 举报
每次看到这题我都会重新写一遍。
  1. package test;

  2. public class Test5 {
  3.        
  4.         public static void main(String[] args) {
  5.                 printStringCombination("abcd");
  6.         }
  7.         //封装一下
  8.         public static void printStringCombination(String string){
  9.                 String[] selected = {""};//初始化已选择字符串数组
  10.                 String[] toSelect = {string};//初始化待选择字符串数组
  11.                 combine(selected, toSelect, string.length());//开始选择
  12.         }
  13.         //打印组合的具体实现,需要递归
  14.         private static void combine(String[] selected,String[] toSelect,int length) {
  15.                 if(length==0){//length为待选择字符串的长度,长度为0则退出方法
  16.                         return;
  17.                 }
  18.                 /*
  19.                  * ------------初始------------
  20.                  * 已选择:空串                对应未选择:abc
  21.                  * ------------选第一个------------
  22.                  * 已选择:                对应未选择:
  23.                  * a                        bc
  24.                  * b                        ac
  25.                  * c                        ab                共 1*3=3种
  26.                  * ------------选第二个------------
  27.                  * 已选择:                对应未选择:
  28.                  * ab                        c
  29.                  * ac                        b
  30.                  * ba                        c
  31.                  * bc                        a
  32.                  * ca                        b
  33.                  * cb                        a                共 3*2=6种
  34.                  * 每次选择得到的组合数为 上次已经选择的组合数*待选择字符串的长度
  35.                  */
  36.                 int combinations = selected.length*length;//每次选择得到的组合数
  37.                 String[] newSelected = new String[combinations];//新一轮已选择的组合
  38.                 String[] newToSelect = new String[combinations];//新一轮待选择的组合
  39.                 int count = 0;
  40.                 for (int i = 0; i < selected.length; i++) {
  41.                         for (int j = 0; j < length; j++) {
  42.                                 newSelected[count] = selected[i]+toSelect[i].charAt(j);//选择一个字符拼接到已选择字符串上
  43.                                 //把选择的字符从原待选择字符串中剔除
  44.                                 newToSelect[count] = toSelect[i].substring(0,j)+toSelect[i].substring(j+1);
  45.                                 System.out.print(newSelected[count++]+" ");//打印最新得到的组合
  46.                         }
  47.                 }
  48.                 System.out.println();//换行
  49.                 combine(newSelected, newToSelect, length-1);//递归进行一下次选择
  50.         }
  51. }
复制代码



点评

memorization,很赞,学习了。不过长度为n的字符串排列只是在长度为n-1的排列尾部添一个字符而已,二重循环即可,不一定要递归  发表于 2014-7-24 00:12
回复 使用道具 举报
受教了,也在看这个题
回复 使用道具 举报
花花公子 发表于 2014-7-23 22:59
受教了,也在看这个题

与君共勉
回复 使用道具 举报
David.L 来自手机 中级黑马 2014-7-23 23:46:40
7#
最基础的应该是用数组吧,利用length确定实际个数
回复 使用道具 举报
DSY 中级黑马 2014-7-23 23:59:19
8#
  1. package com.itheima;
  2. import java.util.Scanner;
  3. /**
  4. * 编程列出一个字符串的全字符组合情况,原始字符串中没有重复字符,
  5. * 例如:原始字符串是"abc",打印得到下列所有组合情况
  6. * "a" "b" "c"
  7. * "ab" "bc" "ca" "ba" "cb" "ac"
  8. * "abc" "acb" "bac" "bca" "cab" "cba"
  9. * @author dong
  10. *
  11. */
  12. public class Test6 {
  13.         private String input;                //从输入流中读取的字符串        
  14.     private void getCollection(String strCollection)
  15.     {
  16.       if(strCollection.length() == input.length()){
  17.                     return;              //当迭代到子字符串和原始字符串相同长度时,迭代结束,返回
  18. }
  19.        else{
  20.                for(int i=0;i<input.length();i++){        //循环遍历整个原始数组
  21.                if(strCollection.contains(String.valueOf(input.charAt(i)))){    //判断子字符串是否包含下标为i的原始字符串的字符,如果是就继续循环;没有执行else操作
  22.                continue;
  23.            }
  24.        else{                                                        
  25.                 strCollection +=input.charAt(i);                //将子字符串中没有的字符添加到子字符串中
  26.                 System.out.println(strCollection);              //打印输出
  27.                 getCollection(strCollection);                   //进行下一轮迭代
  28.                 strCollection = strCollection.substring(0, strCollection.length()-1);//将刚添加到子字符串中的字符去掉。
  29.             }
  30.           }
  31.        }
  32.     }
  33.      public static void main(String[] args) {
  34.                 System.out.println("请输入字符串");
  35.                 Scanner in = new Scanner(System.in);
  36.             Test6 test = new Test6();
  37.             test.input = in.next();
  38.             test.getCollection("");
  39.     }
  40. }
复制代码
回复 使用道具 举报
MGC 中级黑马 2014-7-24 00:06:47
9#
学习了,很不错,多发这种帖子
回复 使用道具 举报
明早试做看
回复 使用道具 举报
三重循环,无递归。
  1. import java.util.ArrayList;

  2. /*
  3. * 输入N个字符,如'a','b','c',打印出所有组合
  4. * a b c
  5. * ab ac bc ba bc cb
  6. * abc acb bac bca cba cab
  7. *
  8. * 思路:
  9. *   长度为n的字符串排列,是长度为n-1的每个字符串排列的末尾加上一个字符
  10. *   比如,abc是由ab末尾加c得到的;acb是由ac末尾加c得到的。
  11. *   因此,用一个ArrayList不断添加已得到的排列结果。当要排列长度为n的字符串时,让两个指针分别指向长度为n-1的排列在结果集合中的起止下标
  12. */

  13. public class Permute {

  14.         public static void main(String[] args) {

  15.                 String s = "abc";
  16.                 printPermute(s);
  17.         }
  18.         
  19.         public static void printPermute(String str) {
  20.                 char[] candidates = str.toCharArray();
  21.                 int len = str.length();
  22.                 ArrayList<String> permutations = new ArrayList<String>(); // 存储排列结果
  23.                 // 长度为1的排列,直接添加
  24.                 for (char c : candidates)
  25.                         permutations.add(Character.toString(c));
  26.                 // 下标指针,分别指向长度为1的字符串排列的起止位置
  27.                 int start = 0;
  28.                 int end = permutations.size();

  29.                 // 长度2到len的排列,用循环完成
  30.                 for (int i = 2; i <= len; i++) {
  31.                         // 下面的二重循环,外层循环遍历长度为n-1的每一个字符串排列
  32.                         for (; start < end; start++) {
  33.                                 String s = permutations.get(start);
  34.                                 // 内层循环则尝试在长度为n-1的字符串排列的尾部添加一个字符,形成一个长度为n的字符串
  35.                                 for (char c : candidates) {
  36.                                         // 只添加不重复的字符
  37.                                         if (s.indexOf(c) == -1)
  38.                                                 permutations.add(s + c);
  39.                                 }
  40.                         }
  41.                         // 经过循环,start已经指向长度为n-1的字符串排列在结果集合中的起始位置
  42.                         // 现在让end指向指向长度为n-1的字符串排列在结果集合中的终止位置
  43.                         end = permutations.size();
  44.                         // 开始下一次循环,处理长度为n的字符串排列
  45.                 }
  46.                
  47.                 // 打印结果集合及其元素个数
  48.                 System.out.println(permutations);
  49.                 System.out.println(permutations.size());
  50.         }
  51. }
复制代码
回复 使用道具 举报
这个问题,貌似做过
回复 使用道具 举报
我也有这个题目 呵呵
回复 使用道具 举报
升级一下我4楼中的算法,这下不用递归了,直接通过while循环搞定,只要定义一个方法就OK。
  1. package test;

  2. public class CopyOfTest5 {

  3.         public static void main(String[] args) {
  4.                 printStringCombination("abcdef");
  5.         }

  6.         public static void printStringCombination(String string) {
  7.                 String[] selected = { "" };
  8.                 String[] toSelect = { string };
  9.                 int length = string.length();
  10.                 int combinations;// 每次选择得到的组合数
  11.                 while (length != 0) {
  12.                         combinations = selected.length * length;
  13.                         String[] newSelected = new String[combinations];// 新一轮已选择的组合
  14.                         String[] newToSelect = new String[combinations];// 新一轮待选择的组合
  15.                         for (int i = 0, count = 0; i < selected.length; i++) {
  16.                                 for (int j = 0; j < length; j++, count++) {
  17.                                         newSelected[count] = selected[i] + toSelect[i].charAt(j);// 选择一个字符拼接到已选择字符串上
  18.                                         if (length != 1) {// 当待选择数组中的字符串长度为1的时候,就不需要再更改该组合了
  19.                                                 newToSelect[count] = toSelect[i].substring(0, j)
  20.                                                                 + toSelect[i].substring(j + 1);
  21.                                         }
  22.                                         System.out.print(newSelected[count] + "\t");// 打印最新得到的组合
  23.                                 }
  24.                         }
  25.                         System.out.println();
  26.                         selected = newSelected;// 更新已选择组合
  27.                         toSelect = newToSelect;// 更新待选择组合
  28.                         length--;// 待选择组合中的字符串长度减1
  29.                 }
  30.         }
  31. }
复制代码



回复 使用道具 举报
fantacyleo 发表于 2014-7-24 00:46
三重循环,无递归。

我也重写了下。在14楼。
回复 使用道具 举报
赞一个。。。。。。。。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马