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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 奋斗小青年 中级黑马   /  2015-2-27 15:33  /  995 人查看  /  8 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 奋斗小青年 于 2015-2-28 10:52 编辑

7.编程列出一个字符串的全字符组合情况,原始字符串中没有重复字符
原始字符串是"abc",打印得到下列所有组合情况:
                "a" "b" "c"
                "ab" "bc" "ca" "ba" "cb" "ac"
                "abc" "acb" "bac" "bca" "cab" "cba"

我写的时候考虑的是 1.每行字符个数都是递增 2.下一行的字符是建立在上一行的基础上得到的 ,所以在第一行的基础上一次获取第二行第三行...
每行获取之后需要与给定的字符串进行组合,排除重复,然后存储到新集合中,返回新集合即可。
我的代码如下:
  1. import java.util.*;


  2. class Test7 {
  3.         
  4.         public static void main(String[] args)
  5.         {
  6.                 //调用获取子串的方法
  7.                 getSubString("abcd");
  8.         }
  9.         
  10.         //用于获取所有可能子串的方法
  11.         public static void getSubString(String str)
  12.         {
  13.                 //将字符串转成字符数组
  14.                 char[] ch = str.toCharArray();
  15.                
  16.                 //创建一个List集合用于存放字符串集合
  17.                 ArrayList<String> arr = new ArrayList<String>();
  18.                
  19.                 //将{a,b,c}先行存入到集合中用于第二,第三行获取
  20.                 for(int x=0;x<ch.length;x++)
  21.                 {
  22.                         arr.add(ch[x]+"");
  23.                 }
  24.                
  25.                 //有多少字符就有多少行,循环获取每行子串
  26.                 for(int x=0;x<str.length();x++)
  27.                 {
  28.                         //调用getList方法获取每行的子串可能,注意第一行判断
  29.                         if(x!=0)
  30.                                 arr = getList(arr,ch);
  31.                         
  32.                         //利用高级for循环获取集合中元素,也可以用迭代器获取
  33.                         for(String s:arr)
  34.                         {
  35.                                  System.out.print("\"" + s + "\" ");
  36.                         }
  37.                          System.out.println();
  38.                 }
  39.         }
  40.         
  41.         //获取子串可能性的方法
  42.         public static ArrayList<String> getList(ArrayList<String> arr,char[] ch)
  43.         {
  44.                 //新建一个新的集合用于存放新的一行用于返回
  45.                 ArrayList<String> newarr = new ArrayList<String>();
  46.                
  47.                 //对上一行元素进行循环,来得到新的不重复的子串
  48.                 for(String s:arr)
  49.                 {
  50.                         String str = s;
  51.                         //对字符数组中元素进行遍历,如果当前字符串中不含有该元素就将str+ch[i]加入到新的集合中
  52.                         for(int i=0;i<ch.length;i++)
  53.                         {
  54.                                 if(str.indexOf(ch[i]) == -1)
  55.                      {
  56.                              newarr.add(str + ch[i]);
  57.                       }
  58.                         }
  59.                         
  60.                 }
  61.                 //返回新的集合
  62.                 return newarr;
  63.         }
  64. }
复制代码

写完之后看到论坛上有前辈给出的写法是在元素组合部分采用了两重循环同时getList带的参数也多一个,我个人觉得那个循环多余,只需要获取上一行元素对应的List,再用List中元素组合ch中字符就能得到新的一行的List,所以觉得他写的是多余的,我验证结果是相同的,但是也不懂为什么他的也能行,有没有大神能分辨一下?
他的代码如下:
  1. //取得每一行要输出的list集合
  2.         public static ArrayList<String> getList(ArrayList<String> list,int len,char[] ch){
  3.                 //newList 用来装下一行要遍历的元素,list则代表上一行的元素集合
  4.                 ArrayList<String> newList  = new ArrayList<String>();
  5.         
  6.                 //该循环用来取得上一行的元素
  7.                 for(String s:list){
  8.                         String str = s;        
  9.                                 
  10.                                 for(int j = str.length();j < len ;j++){
  11.                                         //遍历字符串中没个元素
  12.                                         for(int i = 0; i < ch.length; i++){
  13.                                                 //字符不重复则将Str+ch[i]添加进集合,
  14.                                                 if(str.indexOf(ch[i]) == -1){
  15.                                                         newList.add(str + ch[i]);
  16.                                                 }
  17.                                         }
  18.                                 }
  19.                                 
  20.                 }
  21.                
  22.                 return newList.size() == 0 ? list:newList;
  23.         }
复制代码






8 个回复

倒序浏览
那位前辈的代码确实是多余了,多余的语句是for(int j = str.length();j < len ;j++) 因为上一行和新一行的长度只差1,内循环就执行一次,没必要搞一个外循环,他这样写了循环也还只是执行一次。不过,也正因为他的 for(int j = str.length();j < len ;j++)是多余而不是错误,所以他仍然得到了正确结果
回复 使用道具 举报
我基础测试也碰到这题了,想了很久都没想出来。他的第一层for循环体中就没有用到参数  j,他只是重复运行多次,如果第一层for循环走1次以上,newList中就会有重复的元素,打印出来肯定是错误的,肯定是他传的len参数刚好等于(str.length()+1),循环走一次就跳出来了,至于最后一句 return newList.size() == 0 ? list:newList;我是看不懂,难道是担心给定的字符串中有相同的字符,
回复 使用道具 举报
兄弟,加油,一起考进黑马
回复 使用道具 举报
shuren2015 发表于 2015-2-27 16:49
兄弟,加油,一起考进黑马

一起加油。
回复 使用道具 举报
shuren2015 发表于 2015-2-27 16:48
我基础测试也碰到这题了,想了很久都没想出来。他的第一层for循环体中就没有用到参数  j,他只是重复运行多 ...

不是,return newList.size() == 0 ? list:newList;其实就是为了返回第一行{a,b,c}元素,当走到它写的那个多余的循环时,如果没有这句,那第一行的元素就返回不了,所以用要判断是否是返回第一行的List,是就直接返回那个循环等于没走,不是就返回新的List。
回复 使用道具 举报
  1. package com.itheima;

  2. /**
  3. * 第7题:编程列出一个字符串的全字符组合情况,原始字符串中没有重复字符,例如:
  4. *                 原始字符串是"abc",打印得到下列所有组合情况:
  5. *                 "a" "b" "c"
  6. *                 "ab" "bc" "ca" "ba" "cb" "ac"
  7. *           "abc" "acb" "bac" "bca" "cab" "cba"
  8. *   
  9. * */

  10. public class Test7 {

  11.         public static void main(String[] args) {
  12.                 //字符串abc
  13.                 String str = "abc";
  14.                 //字符串转换为字符数组
  15.                 char[] array = str.toCharArray();
  16.                 //功能实现函数
  17.                 fun(array);
  18.         }
  19.        
  20.         public static void fun(char[] src){
  21.                 //打印"a" "b" "c"
  22.                 for (int i = 0; i < src.length; i++) {
  23.                         System.out.print(src[i]+" ");
  24.                 }
  25.                 //换行
  26.                 System.out.println();
  27.                 //打印"ab" "bc" "ca" "ba" "cb" "ac"
  28.                 for (int i = 0; i < src.length; i++) {
  29.                         for (int j = 0; j < src.length; j++) {
  30.                                 //判断去重复
  31.                                 if(src[i]==src[j]){
  32.                                         continue;
  33.                                 }
  34.                                 System.out.print(src[i]+""+src[j]+" ");
  35.                         }
  36.                 }
  37.                 //换行
  38.                 System.out.println();
  39.                 //打印"abc" "acb" "bac" "bca" "cab" "cba"
  40.                 for (int i = 0; i < src.length; i++) {
  41.                         for (int j = 0; j < src.length; j++) {
  42.                                 for (int j2 = 0; j2 < src.length; j2++) {
  43.                                         //判断去重复
  44.                                         if((src[i]==src[j])||(src[i]==src[j2])||(src[j]==src[j2])){
  45.                                                 continue;
  46.                                         }
  47.                                         System.out.print(src[i]+""+src[j]+""+src[j2]+" ");
  48.                                 }
  49.                         }
  50.                 }
  51.         }
  52. }
复制代码
回复 使用道具 举报
当时做这道题时,我的思路第一步,字符串变字符数组(因为键盘输入为字符串),第二步:找规律,循环输出是最简便也最快捷的。第三步:去重复,本想写一个去重复函数,但后来发现这样不但增加代码量,而且随着字母组合的复杂还有不但添加代码,于是放弃而采用if直接判断---方便简洁。第四步:分布分功能调试程序,只要思路清晰了,问题也就解决了。个人水平有限,希望大家多多给予指导
回复 使用道具 举报
哎哎~~感觉看起来好难额
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马