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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 戴振良 于 2013-5-1 22:11 编辑

很有意思的一道题目,哎,总感觉自己在做这类题目的时候总是没有思路,尽管看过一些老毕的视频,对于陌生的题目总是找不到思路,我没做出来,我说说我的做题思路,希望可以给我指点指点应该怎样思考。
我的思路是这样的:
一、
一看那图,第一感觉,对,看得出这图应该是有规律的,再想怎么做的时候吧,一个字:晕。
于是我只能先从简单的来,我看外面那圈星星是比较有规律的,以前老毕也讲过星星输出的一些例题,于是我先把这个星星给弄出来,n为3的打印结果为:
*        *        *        *        *
*                                      *
*                                      *
*                                      *
*        *        *        *        *
代码如下:
  1. public static void drawStar(int n) {
  2.                 if (n <= 0) {
  3.                         throw new IllegalArgumentException("参数n必须是大于或等于1的整数");
  4.                 }

  5.                 int starWidth = n + 2;       // 星星的宽度
  6.                 for (int i = 1; i <= starWidth; i++) {              // 控制输出的行数
  7.                         for (int j = 1; j <= starWidth; j++) {    // 控制输出的列数
  8.                                 if (j == starWidth) {                     // 如果是最后一列
  9.                                         System.out.print("*\n");
  10.                                 } else if ((i == 1 || i == starWidth || j == 1)) {    // 如果是第一行、或最后一行、或第一列
  11.                                         System.out.print("*\t");
  12.                                 } else {          // 其他情况                                       
  13.                                         System.out.print(" \t");
  14.                                 }
  15.                         }
  16.                 }
  17.         }
复制代码
二、
星星的输出实现了,我再想数字的输出,这数字的输出关键就在于找出他们的输出规律,对着那些数字看了许久,硬是没思路,于是还是只能从简单的入手,先来规规距距的输出数字,n为3效果如下:
1        2        3
4        5        6
7        8        9
代码如下:
  1. public static void drawNum(int n) {
  2.                 if (n <= 0) {
  3.                         throw new IllegalArgumentException("参数n必须是大于或等于1的整数");
  4.                 }
  5.                 int max = n * n;          // 最大输出数,可用来做结束循环的条件
  6.                 int currentNum = 1;    // 当前要输出的数
  7.                 for (int i = 1; i <= n; i++) {              // 控制输出的行数
  8.                         for (int j = 1; j <= n; j++) {     // 控制输出的列数
  9.                                 if(j!=n) System.out.print(currentNum + "\t");        // 如果不是最后一列
  10.                                 else System.out.print(currentNum + "\n");            // 其他情况
  11.                                 currentNum ++;
  12.                         }
  13.                 }
  14.         }
复制代码
三、
把上面两个效果整合如下:
*        *        *        *        *
*        1        2        3        *
*        4        5        6        *
*        7        8        9        *
*        *        *        *        *
代码如下:
  1. public static void drawCustomShape(int n) {
  2.                 if (n <= 0) {
  3.                         throw new IllegalArgumentException("参数n必须是大于或等于1的整数");
  4.                 }

  5.                 int starWidth = n + 2;    // 星星的宽度
  6.                 int max = n * n;            // 最大输出数,可用来做结束循环的条件
  7.                 int currentNum = 1;      // 当前要输出的数
  8.                 for (int i = 1; i <= starWidth; i++) {            // 控制输出的行数
  9.                         for (int j = 1; j <= starWidth; j++) {   // 控制输出的列数
  10.                                 if (j == starWidth) {                    // 如果是最后一列
  11.                                         System.out.print("*\n");
  12.                                 } else if ((i == 1 || i == starWidth || j == 1)) {        // 如果是第一行、或最后一行、或第一列
  13.                                         System.out.print("*\t");
  14.                                 } else {            // 其他情况
  15.                                         System.out.print(currentNum + "\t");
  16.                                         currentNum ++;
  17.                                 }
  18.                         }
  19.                 }
  20.         }
复制代码
四、
对于数字的螺旋状输出,我实在是找不出规律,所以代码是必定写不出来的。对于我这种笨脑筋,不知道如何思考,麻烦大家给指点指点!


版主,你好,看了您的点评,我也知道它是个正方形,所以我上面代码中外循环与内循环的条件是一样的。哎,我这人就是笨,死脑筋,我的思维不转弯,我就只知道用两个循环,一个循环控制行数,一个循环控制列数,我就只能想到这样:
肯定是一行一行输出的,一行之中又肯定是从左到右一个一个输出的。所以按这样想,比如n=4的那个图中的第二行数字:6  1  2  11,我实在是想不出一个循环怎样能连续输出这4个字的规律(因为死脑筋中认定只能是顺序的小从到大的输出或从大小到的顺序输出,像这种忽大忽小的输出实在是想不出规律),哎,我认输了,等待5月2号答案的公布。这就是人为什么要不断学习的道理了,如果不去学习,这道题就是让我想破头脑我也想不出来怎么做!

点评

不知道你有没有发现,这个题有一个不变的,就是是个矩形,不管你输入多少,都是矩形,既然是矩形,那么它的长度也是确定的。你可以从矩形下手  发表于 2013-5-1 19:02
前辈也来了,多多批评指正啊  发表于 2013-5-1 16:46

评分

参与人数 1技术分 +2 收起 理由
黄玉昆 + 2 鼓励鼓励

查看全部评分

回复 使用道具 举报
本帖最后由 李罡 于 2013-5-1 17:25 编辑

我的方法有点复杂,应该还有更简单的,希望版主给出最优的算法
  1. package cn.itcast.exci6;

  2. import java.util.Scanner;

  3. public class PrintExtc {

  4.         /**
  5.          *思路:
  6.          *用二维数组来存储数据
  7.          *分两种情况:
  8.          *当(n-1)*(n-1)的数组,它的(n-1)为偶数时,则该数组中的最大的元素为max = arr[length-1][0],在最左下的位置,
  9.          *此时定义一个n*n的新的数组,并往该数组里面添加数据++max,用max来记录数据的递增。
  10.          *当(n-1)*(n-1)的数组,它的(n-1)为奇数时,则该数组中的最大的元素为max = arr[0][length-1],在最右上的位置,
  11.          *同上所示,定义一个长度为n的新的数组,并往里面增加数据。
  12.          *
  13.          *我把二维数组
  14.          *1        2
  15.          *4        3
  16.          *当做一个最初的二维数组,然后半圈半圈地增加数据,比如加半圈后得到一个新的二维数组为:
  17.          *         7        8        9        
  18.          *        6        1        2        
  19.          *        5        4        3
  20.          *此时是从最左下 角开始加元素,此时行数增加了一行
  21.          *然后再加半圈为:
  22.          *        7        8        9        10        
  23.          *        6        1        2        11        
  24.          *        5        4        3        12        
  25.          *        16        15        14        13
  26.          *这时是从最右上角开始加元素,加完后行数增加了一行。
  27.          *@author li
  28.          */
  29.         private static int n;
  30.         
  31.         public static void main(String[] args) {
  32.                 //定义一个最初的二维数组
  33.                 int[][] arrOri = {{1,2},{4,3}};
  34.                 System.out.println("输入行数:");
  35.                 Scanner in = new Scanner(System.in);
  36.                 n = in.nextInt();
  37.                 //当行数为1的时候单独打印
  38.                 if(n==1){
  39.                         printArr1();
  40.                 }else{
  41.                 //得到所需要的二维数组,并把它打印出来
  42.                 int[][] arrs =createArr(arrOri);
  43.                 printArr(arrs);
  44.                 }
  45.         }
  46.         //打印数组,并把最外围的一圈*号打印出来
  47.         public static void printArr(int[][] arr){
  48.                 int len = arr.length;
  49.                 for(int i=0;i<len+2;i++)
  50.                         System.out.print("*\t");
  51.                 System.out.println();
  52.                 for(int i =0; i<arr.length ;i++){
  53.                         System.out.print("*\t");
  54.                         for(int j =0;j<arr.length ;j++){
  55.                                 System.out.print(arr[i][j]+"\t");
  56.                         }
  57.                         System.out.println("*");
  58.                 }
  59.                 for(int i=0;i<len+2;i++)
  60.                         System.out.print("*\t");
  61.                 System.out.println();
  62.         }
  63.         public static void printArr1(){
  64.                 System.out.println("*\t*\t*");
  65.                 System.out.println("*\t1\t*");
  66.                 System.out.println("*\t*\t*");
  67.         }

  68.         public static int[][] selectArr(int [][] arr){
  69.                 int len = arr.length;
  70.                 //创建一个新的数组
  71.                 int[][] arr1 = new int[len+1][len+1];
  72.                 if(len%2==0){        
  73.                         //len为偶数时,此时该数组中最大元素在左下角,所以从左下角开始增加元素
  74.                         int max = arr[len-1][0];
  75.                         for(int i=1 ;i<arr1.length ;i++){
  76.                                 int arrRow = arr1.length-i;
  77.                                 arr1[arrRow][0]=++max;
  78.                                 for(int j=1; j<arr1.length ;j++){
  79.                                         arr1[arrRow][j]=arr[arr.length-i][j-1];
  80.                                 }
  81.                         }
  82.                         for(int y=0;y<len ;y++){
  83.                                 arr1[0][y]=++max;
  84.                         }
  85.                         arr1[0][len]=++max;
  86.                 }else{
  87.                         //len为奇数时,此时该数组中最大元素在右上角,所以从右上角开始增加元素
  88.                         int max = arr[0][len-1];
  89.                         for(int i =0;i<arr1.length-1 ;i++){
  90.                                 for(int j=0 ;j<arr.length ;j++){
  91.                                         arr1[i][j] = arr[i][j];
  92.                                 }
  93.                                 arr1[i][arr1.length-1] = ++max;
  94.                         }
  95.                         for(int y=arr1.length-1 ;y>=0 ;y--){
  96.                                 arr1[arr1.length-1][y]=++max;
  97.                         }
  98.                 }
  99.                 //返回所得到的新的数组
  100.                 return arr1;
  101.         }
  102.         
  103.         //得到所需要的n*n行的二维数组。
  104.         public static int[][] createArr(int[][] arr){
  105.                 for(int i=0;i<n-2 ;i++)
  106.                         arr = selectArr(arr);
  107.                 return arr;
  108.         }

  109. }
复制代码

点评

但是还存在一点bug,输入0的时候,是4的结果;是因为你输入0,createArr()方法中的循环并未执行,就直接返回你在main中创建的数组了,希望在改进一下  发表于 2013-5-2 11:24
不在于方法有多简单,而在于你的思路是不是清晰。你的程序不错,思路比较清晰,注释也规范  发表于 2013-5-2 11:22

评分

参与人数 1技术分 +4 收起 理由
黄玉昆 + 4

查看全部评分

回复 使用道具 举报
看看,还要凑齐是个才行能够给看的撒
回复 使用道具 举报
看看是什么
回复 使用道具 举报
呵呵,看看
回复 使用道具 举报
来看看题
回复 使用道具 举报
挑战一下
回复 使用道具 举报
看看题目
回复 使用道具 举报
看看看看!
回复 使用道具 举报
看看看看
回复 使用道具 举报
来看看那
回复 使用道具 举报
看看题,试试看
回复 使用道具 举报
来看看。。
回复 使用道具 举报
  1. /*
  2. 个人感觉,我的这个方法让人有点晕。。。
  3. 1 先将四周的星号放入二维数组中
  4. 2 将左上半部分的数字放入
  5. (1)求出奇数的平方以及在二维数组的位置
  6. (2)根据(1)的值以及下标向左推
  7. (3)根据最左侧数据的信息再向下推
  8. 3 然后用同样的方法,推出右下部分的数据
  9. */
  10. class Circle{
  11.         public static void main(String[] args){
  12.                 int n =4;
  13.                 System.out.println("输入的数n = "+n);
  14.                
  15.                 int m = n+2;//二维数组的维数
  16.                 int[][] arr_2 = new int[m][m];
  17.                
  18.                 twoArr(arr_2);
  19.                 printArr(arr_2);       
  20.                 }
  21. //给二维数组按要求赋值               
  22.         public static void twoArr(int[][] b){
  23.                 int m = b.length;//图形整体的边长
  24.                 int n = m-2;//输出图形中,数字的边长
  25.                 for(int i = 0; i < m; i++){//输入外围星号
  26.                         for(int j = 0; j<m; j++){
  27.                                 if(i == 0||i==(m-1)||j==0||j==(m-1))
  28.                                         b[i][j] = '*';
  29.                                 }
  30.                         }
  31.                        
  32.                 int p = (n+1)/2;//中间数1的下标
  33.                 b[p][p] = 1;

  34.                 for(int i = 1; i <= p;i++){
  35.                         int k,left=0,right = 0;
  36.                         if(b[p-i][p+i] !='*'){
  37.                                 b[p-i][p+i] =(2*i+1)*(2*i+1); //  3   5...奇数的平方
  38.                                
  39.                                 for(k=1;k<((2*i)+1);k++){    //奇数平方的左侧数据
  40.                                         b[p-i][p+i-k] = b[p-i][p+i]-k;
  41.                                         left = b[p-i][p+i-k];//最左侧数据
  42.                                         }       
  43.                                                
  44.                                 for(int h=1;h<((2*i)+1);h++)//转而再向下
  45.                                         b[p-i+h][p+i-(k-1)] = left - h;//用上面推出的最左侧数据的下标,但是这里的k要记得减1
  46.                                
  47.                                 }
  48.                         if(b[p+i][p-i+1]!='*'){
  49.                                 b[p+i][p-i+1]=(2*i)*(2*i);    //   2  4  6...偶数的平方
  50.                                
  51.                                 for(k = 1;k<2*i;k++){                //偶数平方的右侧数据
  52.                                         b[p+i][p-i+1+k] = b[p+i][p-i+1]-k;
  53.                                         right = b[p+i][p-i+1+k];   //最右侧数据
  54.                                         }
  55.                                
  56.                                 for(int h = 1;h<2*i;h++)//转而再向上
  57.                                         b[p+i-h][p-i+1+(k-1)] = right-h;  
  58.                                
  59.                                 }
  60.                         }
  61.                
  62.                 }
  63. //输出二维数组
  64.         public static void printArr(int[][] b){
  65.                 for(int i = 0; i < b.length; i++){
  66.                         for(int j = 0; j<b.length; j++){
  67.                                 if(b[i][j]=='*')
  68.                                            System.out.print((char)b[i][j]+"\t");
  69.                                 else System.out.print(b[i][j]+"\t");
  70.                                 }
  71.                         System.out.println();
  72.                         }
  73.                 System.out.println();
  74.                 }
  75.         }
复制代码

点评

思路较清晰,注释也规范,但希望能把赋值的方法里抽取出来一些功能,不要都放在一起,稍显臃肿,不过很不错,就是在输入0的时候有个bug,望改进  发表于 2013-5-2 11:34

评分

参与人数 1技术分 +3 收起 理由
黄玉昆 + 3

查看全部评分

回复 使用道具 举报
  1. package com.itheima;

  2. public class Test {

  3.         /**
  4.          * @param args
  5.          */
  6.         public static void main(String[] args) {
  7.                 // TODO Auto-generated method stub
  8.                 String[][] heilx = helix2DArray(5);
  9.                
  10.                 for(int i=0;i<heilx.length;i++){
  11.                         for(int j=0;j<heilx.length;j++){
  12.                                 System.out.print(heilx[i][j]+" ");
  13.                         }
  14.                         System.out.println();
  15.                 }
  16.         }
  17.        
  18.         //定义一个螺旋二维数组
  19.         public static String[][] helix2DArray(int size){
  20.                 //数组的大小就是数字的前后各加1
  21.                 int len = size + 2;
  22.                 String[][] heilx = new String[len][len];
  23.                 //遍历数组
  24.                 for(int x=0;x<len;x++){
  25.                         for(int y=0;y<len;y++){
  26.                                 //凡是第一行和最后一行都是*号
  27.                                 if(x==0||x==len-1){
  28.                                         heilx[x][y] = "*\t";
  29.                                 }
  30.                                 //凡是第一列和最后一列都是*号
  31.                                 if(y==0||y==len-1){
  32.                                         heilx[x][y] = "*\t";
  33.                                 }
  34.                         }
  35.                 }
  36.                 /*
  37.                           * * * *  
  38.                         * 1 2 *
  39.                         * 4 3 *
  40.                         * * * *
  41.                        
  42.                         找规律:如果 size是双数 则从 len/2-1开始,否则 len/2
  43.                                         循环size次,分别x和y的变化是: 第一次 y++ 第二次 x++ 第三次 y-- y-- 第四次 x-- x-- 以此类推
  44.                                         有点类似于         y: 1  34   789      131415
  45.                                                                  x:  2    56   101112
  46.                  */
  47.                 if(size%2==0){
  48.                         heilxNumber(heilx, len/2-1, len/2-1, size);
  49.                 }else{
  50.                         heilxNumber(heilx, len/2, len/2, size);
  51.                 }
  52.                 return heilx;
  53.         }
  54.        
  55.         private static void heilxNumber(String[][] heilx,int x,int y,int size){
  56.                
  57.                 //定义让y循环多少次
  58.                 int a = 1;
  59.                 //定义让x循环多少次
  60.                 int b = 1;
  61.                 //定义一个判断y或x是该++还是该--
  62.                 int temp = 1;
  63.                 //存入螺旋数值
  64.                 int h = 1;
  65.                 heilx[x][y] = temp+"";
  66.                 while(temp<=size){
  67.                         for(int i=0;i<a;i++){
  68.                                 if(temp%2==0){
  69.                                         heilx[x][y] = h+"\t";
  70.                                         h++;
  71.                                         y--;
  72.                                        
  73.                                 }else{
  74.                                         heilx[x][y] = h+"\t";
  75.                                         h++;
  76.                                         y++;
  77.                                 }
  78.                         }
  79.                         if(temp<size){
  80.                                 for(int j=0;j<b;j++){
  81.                                         if(temp%2==0){
  82.                                                 heilx[x][y] = h+"\t";
  83.                                                 h++;
  84.                                                 x--;
  85.                                                
  86.                                         }else{
  87.                                                 heilx[x][y] = h+"\t";
  88.                                                 h++;
  89.                                                 x++;
  90.                                         }
  91.                                 }
  92.                         }
  93.                         a++;
  94.                         b++;
  95.                         temp++;
  96.                 }
  97.         }
  98. }
复制代码

点评

注释较规范,思路清晰,但层次不太好,稍微提前出方法,主函数中最好只放置方法名,具体实现功能提前出来即可。输入0的时候存在bug,望改进。  发表于 2013-5-2 11:40

评分

参与人数 1技术分 +3 收起 理由
黄玉昆 + 3

查看全部评分

回复 使用道具 举报
小生,挑战一下。
回复 使用道具 举报
是什么好玩的
回复 使用道具 举报
看下是什么内容
回复 使用道具 举报
不要太难 哦 亲!
回复 使用道具 举报
gjggw123 来自手机 中级黑马 2013-5-2 09:34:17
160#
什么了?定
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马