算法导论:打印回旋数
问题:打印输出逆时针螺旋矩阵,要求螺旋矩阵的阶数由用户输入。例如 n=4时,输出的螺旋矩阵如下:
下面给出我的代码:
1 package org.warnier.zhang.exercises; 2 3 public class Convolution { 4 private int n; 5 private int[][] array; 6 private int number = 1; 7 8 public Convolution(int n) { 9 this.n = n; 10 array = new int[n][n]; 11 init(); 12 } 13 14 private void init() { 15 for (int i = 0; i < n; i++) { 16 for (int j = 0; j < n; j++) { 17 array[i][j] = 0; 18 } 19 } 20 } 21 22 //逆时针方向回旋; 23 public void generateConvolutionNumber() { 24 //处理迭代“内圈”数字输出; 25 int a = 0; 26 int b = n -1 - a; 27 while (b >= a) { 28 //与正常的数组输出方向一致螺旋输出; 29 for (int i = a; i <= b; i++) { 30 for (int j = a; j <= b; j++) { 31 if (i != b && j == a) { 32 array[i][j] = number++; 33 } 34 if (i == b && j != b) { 35 array[i][j] = number++; 36 } 37 } 38 } 39 40 //与正常的数组输出方向相反螺旋输出; 41 for (int i = b; i >= a; i--) { 42 for (int j = b; j >= a; j--) { 43 if (i != a && j == b) { 44 array[i][j] = number++; 45 } 46 if (i == a && j != a) { 47 array[i][j] = number++; 48 } 49 } 50 } 51 52 a ++; 53 b = n -1 - a; 54 } 55 56 //打个补丁:没能解决n为奇数的情况!(没有加上这句代码,中间的空格输出默认值0!) 57 if(n % 2 != 0){ 58 array[n/2][n/2] = number; 59 } 60 } 61 62 public void vprintf() { 63 for (int i = 0; i < n; i++) { 64 for (int j = 0; j < n; j++) { 65 System.out.printf("%3d", array[i][j]); 66 } 67 System.out.println(); 68 } 69 } 70 71 }
简要说明,a 和 b 的存在,是为了解决螺旋输出内圈的数字;下面的是测试代码:
1 package org.warnier.zhang.exercises; 2 3 public class ConvolutionTest { 4 5 public static void main(String[] args) { 6 Convolution convolution = new Convolution(5); 7 convolution.generateConvolutionNumber(); 8 convolution.vprintf(); 9 } 10 11 } 12 13 结果: 14 1 16 15 14 13 15 2 17 24 23 12 16 3 18 25 22 11 17 4 19 20 21 10 18 5 6 7 8 9
这是我的解决方法,主要是将回旋划分为从上到下,从左到右,从下到上,从右到左的四个方向分别处理,要注意后两个方向与正常的数组输出方向相反。这道算法题对学生党来说有点压力,但是掌握了能够写出好多好玩的东西,比如贪吃蛇。上面的算法只是一种可能的实现,欢迎读者贴上自己的代码,交流交流!
根据读者回复,可以通过初始化将所有的数组元素赋值为 n * n 的方式,解决当 n 为奇数时,螺旋输出为默认值0的问题,下面贴上代码:
1 package org.warnier.zhang.exercises; 2 3 public class ConvolutionPro { 4 private int n; 5 private int[][] array; 6 private int number = 1; 7 8 public ConvolutionPro(int n) { 9 this.n = n; 10 array = new int[n][n]; 11 init(); 12 } 13 14 private void init() { 15 for (int i = 0; i < n; i++) { 16 for (int j = 0; j < n; j++) { 17 //使用初始化赋值解决n为奇数的情况! 18 array[i][j] = n * n; 19 } 20 } 21 } 22 23 //逆时针方向回旋; 24 public void generateConvolutionNumber() { 25 //处理迭代“内圈”数字输出; 26 int a = 0; 27 int b = n -1 - a; 28 while (b >= a) { 29 //与正常的数组输出方向一致螺旋输出; 30 for (int i = a; i <= b; i++) { 31 for (int j = a; j <= b; j++) { 32 if (i != b && j == a) { 33 array[i][j] = number++; 34 } 35 if (i == b && j != b) { 36 array[i][j] = number++; 37 } 38 } 39 } 40 41 //与正常的数组输出方向相反螺旋输出; 42 for (int i = b; i >= a; i--) { 43 for (int j = b; j >= a; j--) { 44 if (i != a && j == b) { 45 array[i][j] = number++; 46 } 47 if (i == a && j != a) { 48 array[i][j] = number++; 49 } 50 } 51 } 52 53 a ++; 54 b = n -1 - a; 55 } 56 } 57 58 public void vprintf() { 59 for (int i = 0; i < n; i++) { 60 for (int j = 0; j < n; j++) { 61 System.out.printf("%3d", array[i][j]); 62 } 63 System.out.println(); 64 } 65 } 66 67 }
当然,我们自然想到也可以顺时针螺旋输出,相应地调整上面两个for()的执行顺序即可。