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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 陈圳 高级黑马   /  2013-5-3 19:40  /  2718 人查看  /  10 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 陈圳 于 2013-5-3 21:26 编辑

以前解过螺旋数组,但是开始是用一种很烦琐的方式完成.以致于代码到后自己都看不下去.让我重做我也有当时那个思路,但是完成写出来,却是异常麻烦.
昨天正好解了另一道题.获得思路,于是以一种其他的方式,可以更简单的实现了螺旋数组.
下面给出分析过程:

代码如下:
  1. public class LineArray {

  2.         /**螺旋数组的
  3.          * @param args
  4.          */
  5.         public static void main(String[] args) {
  6.                 createArray(7);
  7.         }
  8.         public static void createArray(int n){
  9.                 int index=1;
  10.                 Direction dir=Direction.D;
  11.                 int[][] arr=new int[n][n];
  12.                 int row=n/2,col=n/2,temp=0,step=0;
  13.                 while(index!=n*n){
  14. //                        temp=(step%2==0)?temp+1:temp;
  15.                         if(step%2==0&&step!=(n-1)*2)//这里控制步数的变化,也就是让方向执行到D或A时,步数才增加,其余不加
  16.                                 temp++;
  17.                         if(dir==Direction.D){
  18.                                 for(int i=0;i<temp;i++){
  19.                                         arr[row][++col]=++index;
  20.                                 }
  21.                                 step++;
  22.                         } else if(dir==Direction.S){
  23.                                 for(int i=0;i<temp;i++){
  24.                                         arr[++row][col]=++index;
  25.                                 }
  26.                                 step++;
  27.                         } else if(dir==Direction.A){
  28.                                 for(int i=0;i<temp;i++){
  29.                                         arr[row][--col]=++index;
  30.                                 }
  31.                                 step++;
  32.                         } else if(dir==Direction.W){
  33.                                 for(int i=0;i<temp;i++){
  34.                                         arr[--row][col]=++index;
  35.                                 }
  36.                                 step++;
  37. }
  38.                         dir=dir.nextDirection();//每执行一步,方向会发生变化.变化过程 D->S->A->W
  39.                         for(int i=0;i<arr.length;i++)//打印每一步数组的变化
  40.                                 System.out.println(Arrays.toString(arr[i]));
  41.                         System.out.println("----------------------------------------");
  42.                 }
  43.         }

  44. }
  45. enum Direction{
  46.         D,S,A,W;//四个方向,螺旋数组的行走方向
  47.         public Direction nextDirection(){//循环四个方向
  48.                 switch(this){
  49.                         case D:return S;
  50.                         case S:return A;
  51.                         case A:return W;
  52.                         case W:return D;
  53.                 }
  54.                 return null;
  55.         }
  56. }
复制代码
中间会有一个没有赋值,赋不赋值无所谓了.最主要的是代码有很大的优化余地.因为思路容易懂.
如果哪个高人有空研究,希望能优化一些.谢谢.


评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1 赞一个!

查看全部评分

10 个回复

倒序浏览

回帖奖励 +50

能打印出每一步的变化过程,你没考虑偶数的情况吗?:)
回复 使用道具 举报
lipingan0520 发表于 2013-5-3 20:06
能打印出每一步的变化过程,你没考虑偶数的情况吗?

这个实现了,偶数的就很好实现,有两种方式.第一种,直接取这个方法,返回一个奇数的,再赋上外围的一圈,就能给出一个偶数的排列,
那次挑战时,用的就是那个思路解决的.
当时的思路代码阅读性差.
  1. public static int[][] getArray2(int num,int index){//这个是偶数
  2.              int[][] arr=new int[num][num];
  3.              int[][] temp=getArray1(num-1,index);//这里调用第一个奇数方法,得到奇数螺旋的数组.然后在外围加上一圈就行了
  4.              for(int i=0;i<temp.length;i++)//这里赋值,但总感觉有更好的方式完成这步...
  5.                      for(int j=0;j<temp[i].length;j++){
  6.                              arr[i][j]=temp[i][j];
  7.                      }
  8.              int count=num*num,length=num*2-1;//这里等于4--16;
  9.              for(int i=0;i<=length;i++){//赋上最外层一圈
  10.                      if(i<num)
  11.                              arr[num-1][i]=count--;
  12.                      else
  13.                              arr[length-i][num-1]=count--;
  14.              }
  15.          return arr;
  16.     }
复制代码
第二种就是直接改变起始的位置,都很容易实现,发帖交流最主要是获得一些更好的思路.后期的一些简单实现,我感觉实现不实现就无所谓了.
回复 使用道具 举报
  1. public class LineArray {

  2.         /**
  3.          * 螺旋数组的
  4.          *
  5.          * @param args
  6.          */
  7.         public static void main(String[] args) {
  8.                 createArray(7,true);//true为顺时针输出,false为逆时针输入
  9.         }

  10.         public static void createArray(int n,boolean flag) {//加入一个标记,可以实现逆时针或者顺时针螺旋输出
  11.                 int index = 1;
  12.                 Direction dir;
  13.                 if(flag)
  14.                          dir= Direction.D;
  15.                 else dir= Direction.A;
  16.                 int[][] arr = new int[n][n];
  17.                 int row = n / 2, col = n / 2, temp = 0, step = 0;
  18.                 while (index != n * n) {
  19.                         // temp=(step%2==0)?temp+1:temp;
  20.                         if (step % 2 == 0 && step != (n - 1) * 2)
  21.                                 temp++;
  22.                         if (dir == Direction.D) {
  23.                                 for (int i = 0; i < temp; i++) {
  24.                                         arr[row][++col] = ++index;
  25.                                 }
  26.                                 step++;
  27.                         } else if (dir == Direction.S) {
  28.                                 for (int i = 0; i < temp; i++) {
  29.                                         arr[++row][col] = ++index;
  30.                                 }
  31.                                 step++;
  32.                         } else if (dir == Direction.A) {
  33.                                 for (int i = 0; i < temp; i++) {
  34.                                         arr[row][--col] = ++index;
  35.                                 }
  36.                                 step++;
  37.                         } else if (dir == Direction.W) {
  38.                                 for (int i = 0; i < temp; i++) {
  39.                                         arr[--row][col] = ++index;
  40.                                 }
  41.                                 step++;
  42.                         }
  43.                         dir = dir.nextDirection(flag);
  44.                         for (int i = 0; i < arr.length; i++)
  45.                                 System.out.println(Arrays.toString(arr[i]));
  46.                         System.out.println("----------------------------------------");
  47.                 }
  48.         }

  49. }

  50. enum Direction {
  51.         D, S, A, W;// 四个方向,螺旋数组的行走方向
  52.         public Direction nextDirection(boolean flag) {// 循环四个方向
  53.                 if(flag){
  54.                         switch (this) {
  55.                         case D:        return S;
  56.                         case S:        return A;
  57.                         case A:        return W;
  58.                         case W:        return D;
  59.                         }
  60.                 } else {
  61.                         switch (this) {
  62.                         case A:        return S;
  63.                         case S:        return D;
  64.                         case D:        return W;
  65.                         case W:        return A;
  66.                         }
  67.                 }
  68.                 return null;
  69.         }
  70.        
  71. }
复制代码
因为枚举方向的变化控制,所以简单实现了,程序的逆时针与逆时针的分别输出.
  1. ----------------------------------------
  2. [25, 24, 23, 22, 21]
  3. [10, 9, 8, 7, 20]
  4. [11, 2, 0, 6, 19]
  5. [12, 3, 4, 5, 18]
  6. [13, 14, 15, 16, 17]
  7. ----------------------------------------
复制代码
回复 使用道具 举报
最后优后了...
  1. import java.util.Arrays;
  2. public class LineArray {
  3.         public static void main(String[] args) {
  4.                 createArray(4,true);//true为顺时针输出,false为逆时针输入
  5.         }
  6.         public static void createArray(int n,boolean flag) {//加入一个标记,可以实现逆时针或者顺时针螺旋输出
  7.                 Direction dir;
  8.                 if(flag)//判断顺时针逆时针方向
  9.                          dir= Direction.D;
  10.                 else dir= Direction.A;
  11.                 int[][] arr = new int[n][n];
  12.                 int row,col,temp = 0,step = 0,index = 1;;
  13.                 if(n%2==0)//判断是奇数二维数组还是偶数
  14.                         row=col=n/2-1;
  15.                 else row=col=n/2;
  16.                 arr[row][col]=1;
  17.                 while (index != n * n) {
  18.                         if (step % 2 == 0 && step != (n - 1) * 2)
  19.                                 temp++;
  20.                         for(int i=0;i<temp;i++){//每个方向的循环次数
  21.                                 switch(dir){
  22.                                         case D:arr[row][++col]=++index;break;
  23.                                         case S:arr[++row][col]=++index;break;
  24.                                         case A:arr[row][--col]=++index;break;
  25.                                         case W:arr[--row][col]=++index;break;
  26.                                 }
  27.                                 if(i==temp-1)
  28.                                         step++;
  29.                         }
  30.                         dir = dir.nextDirection(flag);
  31.                         for (int i = 0; i < arr.length; i++)
  32.                                 System.out.println(Arrays.toString(arr[i]));
  33.                         System.out.println("----------------------------------------");
  34.                 }
  35.         }
  36. }
  37. enum Direction {
  38.         D, S, A, W;// 四个方向,螺旋数组的行走方向
  39.         public Direction nextDirection(boolean flag) {// 循环四个方向
  40.                 if(flag){
  41.                         switch (this) {
  42.                         case D:        return S;
  43.                         case S:        return A;
  44.                         case A:        return W;
  45.                         case W:        return D;
  46.                         }
  47.                 } else {
  48.                         switch (this) {
  49.                         case A:        return S;
  50.                         case S:        return D;
  51.                         case D:        return W;
  52.                         case W:        return A;
  53.                         }
  54.                 }
  55.                 return null;
  56.         }
  57. }
复制代码
回复 使用道具 举报
赤裸裸的 显摆啊...回帖有奖励吗??{:soso_e102:}
回复 使用道具 举报
刘胜寒 发表于 2013-5-3 21:46
赤裸裸的 显摆啊...回帖有奖励吗??

只有沙发有...以前一次散的多了.结果发现没人回帖,金币会系统收了...蛋疼
现在每次发帖沙发先来50,多霸气!
回复 使用道具 举报
楼主,我就是用的着方法哦,{:soso_e109:}
回复 使用道具 举报
李德全 发表于 2013-5-3 22:00
楼主,我就是用的着方法哦,

用这种方法很正常.思路想到一块了,代块肯定就跑不远.你把代码也发过来,我们交流一下.这个思路优化空间很大.
回复 使用道具 举报
高手啊,顶一下~
回复 使用道具 举报
陈圳 发表于 2013-5-3 22:30
用这种方法很正常.思路想到一块了,代块肯定就跑不远.你把代码也发过来,我们交流一下.这个思路优化空间很 ...

在那个帖子上
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马