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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 王震阳老师   /  2014-8-11 12:00  /  17250 人查看  /  214 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

반야_바라_밀 发表于 2014-8-14 10:10
楼主大好人,抽空看一下吧。

挺好:
  1. import java.util.Scanner;


  2. public class Sort {

  3.         /**
  4.          * @param args
  5.          */
  6.         public static void main(String[] args) {
  7.                 // TODO Auto-generated method stub
  8.                 System.out.println("请输入一个长度小于10大于等于3的数组,数组中的元素为0~9的整数!");
  9.                 Scanner sc=new Scanner(System.in);//接受键盘输入的数据
  10.                 String in=sc.nextLine();//将键盘输入的数据转换成字符串
  11.                 String[] array=in.split(" ");//将字符床在空格处进行切割,并将结果赋给字符串数组array
  12.                 boolean flag=true;//用于判断输入的数据是否在指定范围内
  13.                 if(array.length<10&&array.length>=3){//判断数组长度是否在指定范围内
  14.                         int[] buf=new int[array.length];
  15.                         try {//如果输入的数据不能转换成int型,则抛出异常
  16.                                 for(int i=0;i<array.length;i++){
  17.                                         buf[i]=Integer.parseInt(array[i]);//便利数组array,并将其中的每一个值转换成int型,并赋给buf
  18.                                         if(buf[i]>9||buf[i]<0){
  19.                                                 flag=false;//如果输入的数据不在0~9之间,则flag为false
  20.                                         }
  21.                                 }
  22.                                 if(flag==true){
  23.                                         allSort(buf,0,buf.length-1);//符合各项规定后对数组buf进行全排列
  24.                                 }else{
  25.                                         System.out.println("输入数据有误,没有在0~9之间!");
  26.                                 }
  27.                                
  28.                         } catch (NumberFormatException e) {
  29.                                 // TODO Auto-generated catch block
  30.                             System.out.println("输入数据有误,不是整数!");
  31.                         }
  32.                 }else{
  33.                         System.out.println("数组长度不合要求!");
  34.                 }
  35.                

  36.         }
  37.        
  38.         //自定义的全排列算法,采用的是递归的思想
  39.         private static void allSort(int[] buf,int start,int end){
  40.                 if(start==end){//当全排列进行到只对数组中的最后一个元素进行全排列是,此时的数组已经是全排列中的一种了,此时输出这个数组
  41.                         for(int i=0;i<=end;i++){
  42.                                 System.out.print(buf[i]);
  43.                         }System.out.println();
  44.                 }else{
  45.                         for(int j=start;j<=end;j++){
  46.                                 int temp=buf[start];
  47.                                 buf[start]=buf[j];
  48.                                 buf[j]=temp;//将传入数组的第一个元素开始依次与后面的元素进行交换,包括数组第一个元素本身
  49.                                
  50.                                 allSort(buf,start+1,end);//将第一个元素与后面的元素交换后,对从下一个元素开始到结尾的这段数组进行全排列
  51.                                
  52.                                 buf[j]=buf[start];
  53.                                 buf[start]=temp;//将交换后的两元素再次交换,回复两个数组元素交换前的位置
  54.                         }
  55.                 }
  56.         }

  57. }
复制代码
回复 使用道具 举报
zeus00456 发表于 2014-8-12 22:56
呈交解答,自认为是相对完善的版本了

里面附带一张示意图,用来说明思路,

思维很好,肯动脑子的程序员:
  1. package com.itheima.bbs.activities.hex_conversion;

  2. import java.io.BufferedReader;
  3. import java.io.IOException;
  4. import java.io.InputStreamReader;
  5. import java.util.Arrays;
  6. import java.util.HashSet;
  7. /**
  8. *题目:将一组数字、字母或符号进行排列,以得到不同的组合顺序,
  9. *例如1 2 3这三个数的排列组合有:1 2 3、1 3 2、2 1 3、2 3 1、3 1 2、3 2 1。
  10. *要求:用户输入一个整数(0到9)数组(数组长度大于等于3,小于10),
  11. *那么请在控制台打印出该数组中所有成员的排列组合。
  12. *详细代码+测试结果才可获得满分。
  13. * @author Gilgamesh
  14. */
  15. /**
  16. * 说明:请老师先看这里
  17. *
  18. * 本程序没有使用递归,而使用密码盘(不知道有没有前人早就想到了,并起了名字,我自己想到的,于是瞎起了一个名)的思路,
  19. * 每一种字符用一个数字代替,这些数字的组合方式就是字符组合的方式,状态是一串数字可以用+1的方式更新
  20. * 就像从000-999找密码箱的密码一样。//附 密码盘示意图。
  21. *
  22. * 本程序可以完成您题目的要求,但是不限于排列数字(是按照您“题目”的描述做的)代码的注释中注明了该法
  23. * 本程序中支持的排序单位有:数字大小写字母和非空白字符(这些字符,比如制表符,排起来会令人费解)
  24. * 虽然题目中规定长度3-10,可以将本程序中密码盘的状态容器改为int型整数,但是,为了以后强化功能方便,使用int数组
  25. * 虽然题目只需要与输入长度相等的排列,本程序注释中依然提供了显示不足输入长度排列的方式,
  26. * 比如123输出(1,2,3,12,13,……)只需按照注释内容放开对应的被注释语句
  27. * 本程序处理了重复的排列,比如112只输出(112,121,211)三个
  28. * 输入空串或全空白符串(比如一堆制表符)可以退出
  29. */

  30. /**
  31. *效果测试:
  32. *输入:1 2 3
  33. *输出:123 132 213 231 312 321
  34. *输入:                1 1 2
  35. *输出:112 121 211//去掉了重复
  36. *输入:
  37. *输出:程序结束,谢谢您的使用
  38. *==========
  39. *显示不足输入长度排列的方式中//请您在程序中搜索“列出不足”,并按注释放开注释
  40. *输入:                1 2    3
  41. *输出:1 2 3 12 13 21 23 31 32 123 132 213 231 312 321
  42. *输入:112
  43. *输出:1 2 11 12 21 112 121 211 //去掉了重复
  44.   *输入:
  45. *输出:程序结束,谢谢您的使用
  46. *
  47. *在任意种模式,输入不满足条件都会被继续要求输入
  48. */
  49. public class Permutation_Pombination {       
  50.                 //为了操作方便,直接静态一个容器
  51.                 static char[] chs =null;
  52.                 static HashSet<Integer> pastStat = new HashSet<Integer>();//保持排列哈希值
  53.                 public static void main(String[] args) {
  54.                         //洁净清爽的主方法
  55.                         //循环功能
  56.                         do{//可以省去while中对chs判空,提高效率
  57.                                 chs = getInputInfo();//通过方法获取用户输入
  58.                                 getPermutationAndPombination(chs);//排列
  59.                                 pastStat.clear();
  60.                         }while(chs[0]!=' ');//退出标记为空格,因为’ ‘为禁用字符
  61.                         System.out.println("程序结束,谢谢您的使用");
  62.                 }
  63.                 /**
  64.                  * 输入方法
  65.                  */
  66.                 static char[] getInputInfo() {
  67.                                 String s =null;
  68.                                 //打印提示信息
  69.                                 while(!isChsInLaw(s)){//输入不合法就卡在这里吧^_^
  70.                                         System.out.println("本程序用来获得一串数字、字母、符号的排列组合,请您输入您要输入的数字\n" +
  71.                                                         "本程序支持对3-10个单位进行排列组合,您可以用空格分隔每个单位," +
  72.                                                         "也可以不分隔,程序将自动识别每个单位" +
  73.                                                         "建议您输入不重复的字符,但是本程序已经处理了重复排列");
  74.                                         //开一个流读用来获得用户的输入
  75.                                         BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  76.                                         //获得用户输入的字符串
  77.                                         try { s = br.readLine(); } //处理异常
  78.                                                 catch (IOException e) {/*我们不希望用户看到任何异常,作为补偿,我们在代码中添加功能保证能获得合法的输入*/}
  79.                                         br=null;//释放流
  80.                                 }//输入合法通过,但是有可能数组中被注入了结束标记' '
  81.                         return chs;
  82.                 }
  83.                 /**
  84.                  * 判断用户的输入是否合法的方法
  85.                  */
  86.                 private static boolean isChsInLaw(String s) {
  87.                         if(s==null)//空串非法
  88.                                 return false;
  89.                         if (s.matches("^ *$")){//字符串全是空格(全是禁用字符)或长度为零(明显是不想玩了)时退出
  90.                                 chs=new char[]{' '};//做个标记而已,让数组中出现禁用字符
  91.                                 return true;//既然不想玩了,就不用非要得到正确输入了
  92.                         }
  93.                         String noSpaceString = s.replaceAll("([\\s]*)+", "");//去除空白(非法字符)字符
  94.                         //将下面的正则变为-->"[0-9]{3,10}"可按题目限定只排数字
  95.                         if (noSpaceString.matches(".{3,10}")){//允许3-10位数字 字母 非空符号
  96.                                 chs = noSpaceString.toCharArray();
  97.                                 return true;
  98.                         }
  99.                         return false;//不是空串不满足上面条件返回假
  100.                 }
  101.                 /**
  102.                  * 用来排列的方法
  103.                  */
  104.                 private static void getPermutationAndPombination(char[] chs) {
  105.                         if(chs[0]==' ')return;//带着结束标记不用排
  106.                         //根据字符串的位数(数组的位数)建立状态(密码)盘
  107.                         //用chs数组的索引作为该字符的状态码
  108.                         //0对应数组第一位,1对应数组第二位,2对应数组第三位.....
  109.                         int[] stat = new int[chs.length];
  110.                         /*
  111.                          * 如果需要列出不足数组长度的排列,请解开注释
  112.                          //将整个密码盘用-1填充,-1表示此位尚未被使用
  113.                          **/ Arrays.fill(stat, -1);
  114.                          
  115.                         //获取每一位的最大状态值(就是上面两个数组的最大索引)
  116.                         int max = stat.length-1;
  117.                         while(!isComplete(stat)){//如果密码盘没有遍历完成,就继续,否则退出
  118.                                 //每一轮,密码盘的末位+1
  119.                                 stat[max]++;
  120.                                 //如果末位数值达到单个位的上限就向上进位,本位归0(就像数数一样)
  121.                                 for(int i = max ;i>=0 ;i--){
  122.                                         if (stat[i]==max+1){
  123.                                                 stat[i]=0;
  124.                                                 stat[i-1]++;
  125.                                         }
  126.                                 }//此时,密码盘中保存了一个状态密码
  127.                                 if (isInLaw(stat)){//判断这个状态十分符合要求(没有重复)
  128.                                         //如果这个状态是可用的,就输出状态对应的字符串
  129.                                         int hashValue = getHashValue(stat);//每一种排列的哈希值唯一
  130.                                         if(pastStat.contains(hashValue)) continue;//如果容器中有哈希值,此排列曾出现,跳出
  131.                                         else
  132.                                                 pastStat.add(hashValue);//添加没有出现过的哈希值
  133.                                         for(int val : stat)//遍历状态
  134.                                                 /*如果需要列出不足数组长度的排列,请解开注释
  135.                                                  **/ if(val == -1)continue;//跳过没有使用的位以提高效率
  136.                                                 else
  137.                                                         System.out.print((char)chs[val]);//打印状态对应的字符
  138.                                         System.out.println();
  139.                                 }
  140.                         }
  141.                 }
  142.                 /**
  143.                  * 获取排列哈希值的方法
  144.                  */
  145.         private static int getHashValue(int[] stat) {//相当于复写了char[]的hashCode方法,复写后哈希值对于每一种排列唯一(不绝对但是概率极低)
  146.                         int hashValue = 0;
  147.                         for (int i = 0; i<stat.length;i++){
  148.                                 hashValue = hashValue * 31 + ((stat[i]==-1)?0:chs[stat[i]]);
  149.                         }
  150.                         return hashValue ;
  151.                 }
  152.         /**
  153.          * 判断这个状态十分符合要求,要求是密码盘中没有重复的元素
  154.          */
  155.         private static boolean isInLaw(int[] stat) {//在此步无法检测重复排列
  156.                 boolean flag = true;//定义一个标记
  157.                 for (int i=0;i<stat.length;i++){
  158.                         //遍历当前状态的每一位,跳过未使用的位
  159.                         /*如果需要列出不足数组长度的排列,请解开注释
  160.                          * */if (stat[i]==-1)continue;
  161.                         else
  162.                                 //从第一个有效位开始,判断和后面的每一位都不重复
  163.                                 for (int j = i+1;j<stat.length;j++){
  164.                                         if(stat[i]==stat[j]) {//若相等,证明当前位和后面的某位相等,说明有重复位不满足条件
  165.                                                 flag = false;        //有一次不满足就将标记置为假,跳出
  166.                                                 break;
  167.                                         }
  168.                                 }
  169.                 }
  170.                
  171.                 //若被置位为假,返回假;否则返回默认的真
  172.                 return flag;               
  173.         }
  174.         /**
  175.          * 判断密码盘有没有遍历完成,它的完成意味着排列动作的完成
  176.          */
  177.         private static boolean isComplete(int[] stat) {//状态的每一位都是最大值时完成排列
  178.                 int max = stat.length-1 ;//获取状态长度
  179.                 boolean flag = true;//定义标记
  180.                 for(int st : stat){//只有标记为真才有判断下一位的必要
  181.                         if(flag==true)
  182.                                 if(st!=max) {
  183.                                         //只要某一位不等于单个位上的最大值,就将标记置为假,跳出
  184.                                         flag = false;
  185.                                         break;
  186.                         }
  187.                 }//若没跳出,返回真,整个密码盘遍历完成;否则说明某一位不满足遍历完成的条件,返回假
  188.                 return flag;
  189.         }
  190. }
复制代码
回复 使用道具 举报

很好:
  1. import java.util.*;

  2. public class FullSort {
  3.         /**
  4.          * 递归算法:将数据分为两部分,递归将数据从左侧移右侧实现全排列
  5.          *
  6.          */
  7.         private static void sort(List<String> datas, List<String> target, int length) {
  8.                 if (target.size() == length) {
  9.                         for (Object obj : target)
  10.                                 System.out.print(obj);
  11.                         System.out.println();
  12.                         return;
  13.                 }
  14.                 for (int i = 0; i < datas.size(); i++) {
  15.                         List<String> newDatas = new ArrayList<String>(datas);
  16.                         List<String> newTarget = new ArrayList<String>(target);
  17.                         newTarget.add(newDatas.get(i));
  18.                         newDatas.remove(i);
  19.                         sort(newDatas, newTarget, length);
  20.                 }
  21.         }

  22.         public static void main(String[] args) {
  23.                 System.out.println("请输入一个长度大于等于3,小于10整数:");
  24.                 // 从System.in中读取一个数
  25.                 Scanner s = new Scanner(System.in);
  26.                 //获取输入的数。
  27.                 String num = s.nextLine();
  28.                 //使用split进行分割字符串
  29.                 String data[] = num.split("");
  30.                 //在创建一个数组,长度少于data
  31.                 String[] datas = new String[data.length - 1];
  32.                 //将数组data中的有效字符付给数组datas
  33.                 for (int x = 0; x < data.length; x++) {
  34.                         if (x == data.length - 1)
  35.                                 continue;
  36.                         datas[x] = data[x + 1];
  37.                 }
  38.                 // 设置为待排列数组的长度即实现全排列
  39.                 int length = datas.length;
  40.                 if(length>=3 && length<10){
  41.                         System.out.println("数"+num+"的全排列:");
  42.                         sort(Arrays.asList(datas), new ArrayList<String>(), length);
  43.                 }else
  44.                         System.err.print("您输入的数不在范围内!");
  45.         }
  46. }
复制代码
回复 使用道具 举报
沿途小将 发表于 2014-8-13 21:04
以后还要这种好事,直接找我

不好意思!由于第一次提交错了,后改了,造成提交了两次
回复 使用道具 举报
提交答案,今天提交还来得及么?

Demo0811.rar

22.56 KB, 阅读权限: 200, 下载次数: 1

评分

参与人数 1技术分 +3 收起 理由
王震阳老师 + 3 赞一个!

查看全部评分

回复 使用道具 举报
不知道算不算过期啊,现在,急求分啊

RangeTest.zip

754 Bytes, 阅读权限: 200, 下载次数: 0

排序

回复 使用道具 举报
yesecongcong 发表于 2014-8-15 20:22
不知道算不算过期啊,现在,急求分啊

这怎么上面答案都出来了,看来我迟到了
回复 使用道具 举报
看题目的
回复 使用道具 举报
。。。。。。。。。。。。。。。。。。。。。。
回复 使用道具 举报
子阳zy 来自手机 中级黑马 2014-8-16 23:26:31
110#
威武……
回复 使用道具 举报
令题了啊啊啊
回复 使用道具 举报
题目题目题目
回复 使用道具 举报
虽然过期了就当练习做了
回复 使用道具 举报
黑马程序员,我来了!
回复 使用道具 举报
让我看看能拿到技术分不
回复 使用道具 举报
我是来领题的。
回复 使用道具 举报
回帖领题
回复 使用道具 举报
先来看看题
回复 使用道具 举报
领题,拿分,进黑马,做精英
回复 使用道具 举报
看看题目啊
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马