明确了方阵数字是螺旋递增以后,发现每一个“口”字型的一圈数字正好闭合且连续递增。所以解题思路是由“口”字型的
递增依次向内嵌套。先填充最外层“口”字型的一圈数字,接着填充次外层……最后填充最内层的四个数。由一些较简单的画图可以
看出,层数的奇偶会影响到最内层的填充。当为奇数时,最内层只剩一个数字需要填充。所以奇数层需要单独考虑。
先是填充顶部的(n-1)个数字,接着由顶部的最后一个数字开始向下,填充右部的(n-1)个数字,接着是底部的(n-1)个和左部的(n-1)个,这样就填充了最外层的一圈“口”字型数字。(定一个静态的成员变量,从1开始,每填充一次,自增一次),依照同样的方法填充次外层,第三层……一直到偶数层的最内层。
*
填充的算法是:每一层未填充的个数是(n-2*l)个,n是总层数,l是当前层数,为了便于数组的计算,这里层数也是从0开始,
* 即l=0时是第一层。每一轮填充都是从(l,l)开始的。←---字母l,不是数字1。 但是每一层都需要为邻边的填充留一个地方,比如填充顶部的时候,需要留出一个位置作为填充右部的开始,所以真正需要填充的个数是(n-2*l-1)。
* 当层数为l时,每一边的起始坐标分别是(上,右,下,左):
* (l,l)
* (l,n-l-1)
* (n-1,n-1)
* (n-1,l)
*
* 当层数为偶数层的时候,恰好最后一层每一边填充一个数。当层数为奇数层的时候,最后一层只剩一个数未填充(n-2*l-1)=0,所以需要手动将最后一个数填充进方阵中。
*
* 最后将填充好的方阵打印在控制台上。以上就是本题的思路和解决办法。
public static void main(String[] args) { System.out.println("输入方阵的层数(层数过大方阵的可读性会变差):"); Scanner sc = new Scanner(System.in); //层数 int n = sc.nextInt(); //填充的数字,没填充一次自增一次 int var = 1; //方阵的中间,表示需要循环的次数,或者需要填充的“口”字个数。 int limit = (int)Math.ceil(n/2.0) - 1; //定义一个n×n的矩阵来存储填充的数字 int[][] metrix = new int[n][n]; //嵌套的层数,循环limit次---limit个“口” for(int l=0;l<=limit;l++){ /*填充顶部 * 填充这一层时,i(横坐标)不变,j(纵坐标)递增,直到填充了(n-2*l-1)个数后退出这一层循环。 */ for(int i=l,j=i;j<l+(n-2*l-1);j++){ metrix[i][j] = var++; } /*填充右边 * 填充这一层时,j(纵坐标)不变,i(横坐标)递增,直到填充了(n-2*l-1)个数后退出这一层循环 */ for(int j=n-l-1,i=l;i<l+(n-2*l-1);i++){ metrix[i][j] = var++; } /*填充底部 * 填充这一层时,i(横坐标)不变,j(纵坐标)递减,直到填充了(n-2*l-1)个数后退出这一层循环。 */ for(int i=n-l-1,j=i;j>(n-l-1)-(n-2*l-1);j--){ metrix[i][j] = var++; } /*填充左边 * 填充这一层时,j(纵坐标)不变,i(横坐标)递减,直到填充了(n-2*l-1)个数后退出这一层循环 */ for(int i=n-l-1,j=l;i>(n-l-1)-(n-2*l-1);i--){ metrix[i][j] =var++; } } //当层数是奇数时,以上算法并没有处理处于最中间的数,这里需要单独处理。 if(n%2==1 && metrix[limit][limit] == 0){ metrix[limit][limit] = var; } //打印 printMetrix(metrix); } //打印矩阵,如果层数过高,需要将数字间的间隔加大(比如加更多的\t),否则可读性级差。 public static void printMetrix(int[][] metrix){ for(int i=0;i<metrix.length;i++){ for(int j=0;j<metrix[i].length;j++){ System.out.print(metrix[i][j] + "\t\t"); } System.out.println(); } }
原文:http://my.oschina.net/sherwayne/blog/297687