黑马程序员技术交流社区

标题: 没有思路 [打印本页]

作者: haohanlinyu    时间: 2014-6-9 16:27
标题: 没有思路
本帖最后由 haohanlinyu 于 2014-6-10 22:58 编辑

编程列出一个字符串的全字符组合情况,原始字符串中没有重复字符,例如:

         原始字符串是"abc",打印得到下列所有组合情况:
   "a" "b" "c"
   "ab" "bc" "ca" "ba" "cb" "ac"
   "abc" "acb" "bac" "bca" "cab" "cba"
*/
作者: crazylong    时间: 2014-6-9 17:26
我也是有点乱
作者: 汤姆纳斯    时间: 2014-6-9 18:30
同样不知,等待高手解答
作者: 123_yaya    时间: 2014-6-9 18:45
额 我基础测试碰到的就是这道题。。楼主可以参考一下。。
  1. package com.study.two;


  2. import java.util.ArrayList;
  3. import java.util.List;


  4. /**
  5. *
  6. *  编程列出一个字符串的全字符组合情况,原始字符串中没有重复字符
  7. 例如:
  8. 原始字符串是"abc",打印得到下列所有组合情况
  9. "a" "b" "c"
  10. "ab" "bc" "ca" "ba" "cb" "ac"
  11. "abc" "acb" "bac" "bca" "cab" "cba"
  12. *
  13. */
  14. /**
  15. * 思路:1.先把字符串转化为数组
  16. *     2.先是进行数组的排列组合
  17. *     例如输入abc,那么输出的组合应该是a,b,c,ab,ac,bc,abc。
  18. *     3. 然后再是数组的全排列
  19. *     如输入的是abc,则输出的是abc,acb,bac,bca,cab,cba。
  20. *     4. 最后结合起来可以得出题目结果
  21. *
  22. *
  23. */
  24. public class Test5 {
  25.     //数组的排列组合,例如输入abc,那么输出的组合应该是a,b,c,ab,ac,bc,abc。
  26.         //算法:假设我们想在长度为n得字符串中求m个字符的组合。我们先从头扫描字符串的第一个字符,针对第一个字符有两种选择。
  27.         //一种是把该字符放进集合里,然后对剩下的n-1个字符中挑出m-1个字符。
  28.         //另一种是不把该字符放进集合里,然后是对剩下的n-1个字符中挑出m个字符。
  29.         //combination(char chs[])方法和combine(char []cs,int begin,int number,List <Character>  list)
  30.         //方法是上面的排列组合的实现。最后再在排列组合的基础上加上(全排列组合)。则可以实现题目的要求。
  31.         public static void combiantion(char chs[]){
  32.                 //如果数组为空则返回空
  33.                 if(chs==null||chs.length==0){
  34.                         return ;
  35.                 }
  36.                 //定义集合接收排列组合结果
  37.                 List  <Character>  list=new ArrayList<Character>();
  38.                 //字符串的1个,2个,3个....字符总长长度,字符的排列组合
  39.                 for(int i=1;i<=chs.length;i++){
  40.                         //从0位置开始扫描
  41.                         combine(chs,0,i,list);
  42.                 }
  43.         }
  44.         //从字符数组中第begin个字符开始挑选number个字符加入list中
  45.         public static void combine(char []cs,int begin,int number,List <Character>  list){
  46.        //当挑选的字符数扫描到0时,将集合中的数据取出来进行全排列组合
  47.                 if(number==0){
  48.                 char cc[]=new char[list.size()];
  49.                 for(int j=0;j<list.size();j++){
  50.                         cc[j]=list.get(j);
  51.                 }
  52.                 //对排列组合后的字符进行全排列
  53.                 permutation(cc, 0);
  54.                 return ;
  55.         }
  56.                 //当begin位循环到字符最后时,不再向下扫描,否则抛出数组溢出异常
  57.         if(begin==cs.length){
  58.                 return;
  59.         }
  60.         //第一种情况,扫描到的第一个字符,加入的集合中去
  61.         list.add(cs[begin]);
  62.         //从剩下的字符中,扫描number-1个字符到集合中区
  63.         combine(cs,begin+1,number-1,list);
  64.         //第二种情况,扫描到的第一个字符不加入集合里头去,移除添加到数组中的字符
  65.         list.remove((Character)cs[begin]);   
  66.         //从子符数组下一位挑选number个字符放入list中
  67.         combine(cs,begin+1,number,list);
  68.         }
  69.         //数组的全排列组合
  70.         //如输入的是abc,则输出的是abc,acb,bac,bca,cab,cba。
  71.         //算法:如abcde 首先是首位是a的情况下,全排列剩下的。然后交换1-2位数字,即首位是b的情况,全排列的。以此类推。
  72.         //用permutation自身对剩下的数组进行全排列,在permutation函数内,
  73.         //只要判断出来数组中只有一个元素时,无需再排列,直接打印数组即可。
  74.         //因为依次对1-2位,2-3位,1-4位进行交换,所以每次交换后,需要再次交换,使数组归位。
  75.         public static void permutation(char[]ss,int i){
  76.                 //为了交换数据,定义中间变量
  77.                 char temp;
  78.                 if(ss==null||i<0||i>ss.length){
  79.                         return;
  80.                 }
  81.                 if(i==ss.length){
  82.                         System.out.println(new String(ss));
  83.                 //输出排列
  84.                 }else{
  85.                         for(int j=i;j<ss.length;j++){
  86.                                 //交换前缀,使之产生下一个前缀
  87.                                 temp=ss[j];
  88.                                 ss[j]=ss[i];
  89.                                 ss[i]=temp;
  90.                                 //对i+1位之后剩下的元素进行全排列
  91.                                 permutation(ss,i+1);
  92.                                 //将前缀换回来,继续做上一个的前缀排列.
  93.                                 temp=ss[j];
  94.                                 ss[j]=ss[i];
  95.                                 ss[i]=temp;
  96.                         }
  97.                 }
  98.         }
  99.         public static void main(String args[]){
  100.             String str=new String("abcd");
  101.             //字符串转换成数组
  102.             char chss[]=str.toCharArray();
  103.                 combiantion(chss);
  104.         }
  105.   
  106. }
复制代码

作者: a6217815    时间: 2014-6-9 18:51
同只能写到一半,可能思路有问题, 吃完饭回来看楼上的代码
作者: haohanlinyu    时间: 2014-6-9 18:58
123_yaya 发表于 2014-6-9 18:45
额 我基础测试碰到的就是这道题。。楼主可以参考一下。。

你太厉害了   你学了多长时间  ??(我看完一遍视频   但没敲代码  光在本上记笔记了  效率不高 )能把你的学习方法 分享下吗 ?(我正在申请入学当中  ,遇到了很多问题,感觉自己的基础的提升空间很大呀!!)
作者: 123_yaya    时间: 2014-6-9 19:04
haohanlinyu 发表于 2014-6-9 18:58
你太厉害了   你学了多长时间  ??(我看完一遍视频   但没敲代码  光在本上记笔记了  效率不高 )能把 ...

额 我在校学的就是软件专业的,表示做这题的时候还没怎么看视频。是百度了两天,将网上了两种算法结合起来的。这道题真的很头疼。Lz一定要敲代码哦,只有敲熟了,没有其他更好的办法了。我现在也在学基础了,前面两三个月都在看web的视频,现在回头看基础,基础很不牢固呐。
作者: haohanlinyu    时间: 2014-6-9 19:28
123_yaya 发表于 2014-6-9 19:04
额 我在校学的就是软件专业的,表示做这题的时候还没怎么看视频。是百度了两天,将网上了两种算法结合起 ...

敲视频里的代码还是  自己找题联系    视频里的有点墨迹 时间太长了

作者: 123_yaya    时间: 2014-6-9 19:40
haohanlinyu 发表于 2014-6-9 19:28
敲视频里的代码还是  自己找题联系    视频里的有点墨迹 时间太长了

我是敲视频里面的代码的,学完就敲,还不一定敲得出来。恩 看视频,看完敲代码确实耗时间,不过时间也耗得值得啦,毕老师讲的都是精华,基础很详细。楼主有空也可以找题练习撒~~。每个人学习方法适合自己就行。
作者: superob123    时间: 2014-6-9 19:46
双重for应该就能搞定
作者: haohanlinyu    时间: 2014-6-9 20:08
superob123 发表于 2014-6-9 19:46
双重for应该就能搞定

怎么弄

作者: 西门吹风    时间: 2014-6-9 21:38
本帖最后由 西门吹风 于 2014-6-9 21:42 编辑

尝试一下,运行来看好像是可以的,没有封装,有点乱
  1. /*
  2. 思路:
  3. a    b    c  与  a   b   c  组合 得到ab  ac  ba  bc  ca  cb
  4. ab  ac  ba  bc  ca  cb    把这个作为数组存起来,再与  a  b  c组合,如此循环
  5. 其中当前一个字串包含后面的字串时,用continue跳过

  6. 1、把原始字符串转成字符串类型数组arr1
  7. 2、新建一个字符串类型数组变量arr2,用于指向中间的组合,初始指向原始字串数组
  8. 3、原始数组与原始数组组合,把得到的结果先成一个字串,每个结果有逗号分开
  9. 4、用逗号分割字串得到数组,并用arr2指向该数组
  10. 5、用中间组合数组arr2与原始字符串数数组arr1组合,如此循环
  11. */
  12. class ZhuHe
  13. {
  14.         public static void main(String[] args)
  15.         {
  16.                 zhuHe("abcef");
  17.         }
  18.         public static void zhuHe(String str)
  19.         {
  20.                 char[] arr=str.toCharArray();
  21.                 String[] arr1=new String[arr.length];
  22.                 for(int i=0;i<arr.length;i++)
  23.                 {
  24.                         arr1[i]=arr[i]+"";
  25.                         System.out.print(arr1[i]+" ");
  26.                 }
  27.                 System.out.println();
  28.                 String[] arr2=arr1;
  29.                 for(int x=0;x<arr.length-1;x++)   //第一层需要与原始字串数组合的次数
  30.                 {
  31.                         String s="";
  32.                         for(int i=0;i<arr2.length;i++)     //第二层控制中间组合数组
  33.                         {
  34.                                 for(int j=0;j<arr1.length;j++)    //第三层控原始的字符串数组
  35.                                 {
  36.                                         if(arr2[i].contains(arr1[j]))
  37.                                                 continue;                                
  38.                                         s=s+arr2[i]+arr1[j]+",";     
  39.                                 }
  40.                         }
  41.                         s=s.substring(0,s.length()-1);
  42.                         arr2=s.split(",");
  43.                         for(int k=0; k<arr2.length;k++)
  44.                         {
  45.                                 System.out.print(arr2[k]+" ");
  46.                         }
  47.                         System.out.println();
  48.                 }
  49.         }
  50. }
复制代码




作者: 泛小型    时间: 2014-6-9 21:43
多看源码
作者: superob123    时间: 2014-6-9 22:53
西门吹风 发表于 2014-6-9 21:38
尝试一下,运行来看好像是可以的,没有封装,有点乱

这个思路真的很好,很厉害
作者: axuan    时间: 2014-6-9 22:57
   static int count = 0;
static char[] array = { 'a', 'b', 'c' };
static LinkedList<char[]> list = new LinkedList<char[]> ();
static int[] indexs = new int[3];
static int len = array.length;

public static void main(String[] args){
getSub ();
         for ( char[] cs : list ){
             System.out.println (Arrays.toString (cs));
         }
     }

     private static LinkedList<char[]> getSub (){
         while (count <= len){
             recursionSub (0, -1);
             count++;
         }
         return list;
     }
     
     private static LinkedList <char[]> recursionSub ( int ind, int start ){
start++;
if (start > count - 1){
return null;
}
for ( indexs[start] = 0; indexs[start] < len; indexs[start]++ ){
recursionSub (0, start);
if (start == count - 1){
char[] temp = new char[count];
for ( int i = count - 1; i >= 0; i-- ){
temp[start - i] = array[indexs[start - i]];
}
boolean flag = true;
for ( int i = 0; i < temp.length; i++ ){
for ( int j = i+1; j < temp.length; j++ ){
if (temp[i] == temp[j]){
flag = false;
break;
}
}
}
if (flag){
list.add (temp);
}
}
}
return list;
}
作者: chang清    时间: 2014-6-9 23:11
楼主你好 ! 楼上的同学已经给了你答案了,但是我还是想一下我自己的经验,计算机能处理的都是有规律的(至少我们目前学习的知识是这样)所以拿到一个问题的时候先分析出规律然后写代码相当于是把自然语言翻译成正确的代码,规律出现的特殊情况就特殊处理。说起轻松做起来还是有点难
作者: wyy666    时间: 2014-6-9 23:21
有点意思
作者: cain    时间: 2014-6-9 23:30
我觉得你搞复杂了
作者: JustRight    时间: 2014-6-9 23:31
本帖最后由 JustRight 于 2014-6-9 23:32 编辑

昨天晚上九点开始做,一直到2点,终于做出来了,主要是理解思路,我用的是递归的方法。
  1. package test;

  2. public class ZuHe2 {
  3.         // main方法 控制程序
  4.         public static void main(String[] args) {
  5.                 String s = "abcd";//位数可以随便写,如 a abc  abcd abcde。没有添加健壮性判断,如判空、重复等
  6.                 char[] ch = s.toCharArray();
  7.                 for (int i = 0; i < ch.length; i++) {
  8.                         String[] s1 = diguizuhe(i, ch);// 调用递归,来完成字母的组合
  9.                         print(s1);// 打印组合情况
  10.                 }
  11.         }

  12.         // 递归函数,完成字母的组合
  13.         private static String[] diguizuhe(int i, char[] ch) {
  14.                 // 只用一个字母直接返回本身
  15.                 if (i == 0) {
  16.                         String[] s = new String[ch.length];
  17.                         for (int j = 0; j < ch.length; j++) {
  18.                                 s[j] = ch[j] + "";
  19.                         }
  20.                         return s;
  21.                 }
  22.                 // 大于一个字母,逐层递归
  23.                 while (i > 0) {
  24.                         i--;
  25.                         String[] sum = new String[qiujiecheng(ch.length)];// 设置数组的大小
  26.                         // 逐层拆解,递归组合
  27.                         char[] ch2 = new char[ch.length - 1];
  28.                         int m = 0;
  29.                         for (int j = 0, count = 0; j < ch.length; j++) {
  30.                                 char ch3 = ch[j];
  31.                                 for (int k = 0, k1 = 0; k < ch.length; k++) {
  32.                                         if (j != k) {
  33.                                                 ch2[k1] = ch[k];
  34.                                                 k1++;
  35.                                         }
  36.                                 }
  37.                                 String[] s = diguizuhe(i, ch2);// 用拆分后的新字符串去递归
  38.                                 for (int z = 0; z < s.length && (s[z] != null); z++, m++) {
  39.                                         sum[count] = ch3 + s[z];
  40.                                         count++;
  41.                                 }
  42.                         }
  43.                         // 将得到的字符串数组去空,返回
  44.                         String[] s1 = new String[m];
  45.                         for (int j = 0, x = 0; j < sum.length; j++, x++) {
  46.                                 if (sum[j] != null) {
  47.                                         s1[x] = sum[j];
  48.                                 }
  49.                         }
  50.                         return s1;
  51.                 }
  52.                 return null;
  53.         }

  54.         // 打印字符串数组
  55.         private static void print(String[] s) {

  56.                 for (int j = 0; j < s.length && s[j] != null; j++) {
  57.                         if (j != s.length - 1) {
  58.                                 System.out.print("\"" + s[j] + "\"" + "\t");
  59.                         } else {
  60.                                 System.out.println("\"" + s[j] + "\"");
  61.                         }
  62.                 }
  63.         }

  64.         // 求阶乘,用于确定数组的大小
  65.         private static int qiujiecheng(int n) {
  66.                 int sum = 1;
  67.                 for (int i = 1; i <= n; i++) {
  68.                         sum *= i;
  69.                 }
  70.                 return sum;
  71.         }
  72. }
复制代码


作者: haohanlinyu    时间: 2014-6-10 00:13
感谢各位,热心帮助,感激中。。。我会坚持下去的  一起加油。。。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2