之前去美团面试,被问到如题目的算法问题,因为之前没有解决过类似的问题,所以当时没有答出来,今天在网上搜了一下,都是通过多次循环来实现的,觉得算法效率低,自己琢磨用递归实现一个,实现的思路是用递归,不断变化二维数组的行、列下标来实现螺旋,递增就很简单,有一个值一直++,然后给二维数组相应位置复制就可以了,此算法的难点在于行、列下标状态的变化与增减,不废话了,直接附代码:
public class ArrayAlgorithm { public static void main(String[] args) { int rowMax =10,columnMax=10; int[][] array = new int[rowMax][columnMax]; //rowIncrease(or columnIncrease) 1:增,0不变,-1减 int increase=1,maxNum = rowMax*columnMax,rowIndex=0,columnIndex=0,rowIncrease=0,columnIncrease=1; long start = System.currentTimeMillis(); fillNum(array,rowIndex,columnIndex,rowMax,columnMax,increase,maxNum,rowIncrease,columnIncrease); System.out.println("use time:"+(System.currentTimeMillis()-start)+" ms"); for(int i=0;i<rowMax;i++){ for(int j=0;j<columnMax;j++){ System.out.printf("]",array[i][j]); } System.out.println(); } } /** * 递归实现二维数组顺时针螺旋递增 * @param array 二维数组 * @param rowIndex 行下标 * @param columnIndex 列下标 * @param rowMax 行最大数 * @param columnMax 列最大数 * @param increase 当前递增数 * @param maxNum 最大递增数=rowMax*columnMax * @param rowIncrease 行增减标识,1:增,0:不变,-1:减 * @param columnIncrease 列增减标识,1:增,0:不变,-1:减 */ private static void fillNum(int[][] array,int rowIndex,int columnIndex,int rowMax,int columnMax,int increase,int maxNum,int rowIncrease,int columnIncrease){ if(increase==maxNum){ array[rowIndex][columnIndex]=increase; return; } //给元素赋值 array[rowIndex][columnIndex] = increase++; //根据当前index计算下一个rowIndex和columnIndex //计算rowindex begin boolean rowChangeState = false; switch (rowIncrease){ case 1: if((rowIndex+1)==rowMax||array[rowIndex+1][columnIndex]>0){ rowIncrease=0; columnIncrease=-1; columnIndex--; rowChangeState=true; }else{ rowIndex++; } break; case 0: //不变的情况下,不需要状态的改变,所以不需要写代码 break; case -1: if(rowIndex==0||array[rowIndex-1][columnIndex]>0){ rowIncrease=0; columnIncrease=1; columnIndex++; rowChangeState = true; }else{ rowIndex--; } break; } //计算rowindex end //计算columnindex begin if (!rowChangeState) { //如果行发生状态改变,列的下标值已经被修改,则不再需要判断列的所以值,避免出现二次修改的问题 switch (columnIncrease){ case 1: if((columnIndex+1)==columnMax||array[rowIndex][columnIndex+1]>0){ columnIncrease=0; rowIncrease=1; rowIndex++; }else { columnIndex++; } break; case 0://不变的情况下,不需要状态的改变,所以不需要写代码 break; case -1: if(columnIndex==0||array[rowIndex][columnIndex-1]>0){ columnIncrease=0; rowIncrease=-1; rowIndex--; }else{ columnIndex--; } break; } } //计算columnindex end fillNum(array,rowIndex,columnIndex,rowMax,columnMax,increase,maxNum,rowIncrease,columnIncrease); } }打印输出的结果:
1 2 3 4 5 6 7 8 9 10 36 37 38 39 40 41 42 43 44 11 35 64 65 66 67 68 69 70 45 12 34 63 84 85 86 87 88 71 46 13 33 62 83 96 97 98 89 72 47 14 32 61 82 95100 99 90 73 48 15 31 60 81 94 93 92 91 74 49 16 30 59 80 79 78 77 76 75 50 17 29 58 57 56 55 54 53 52 51 18 28 27 26 25 24 23 22 21 20 19
最后一个需要注意的地方提示一下,如果二维数组很大,如100,在运行时会报StackOverflowError异常,需要在启动参数中加入-Xss2m来修改线程栈的大小,这样就可以运行了。
