任务要求:
从键盘输入一个整数(1~20),则以该数字为矩阵的大小,把1,2,3…n*n的数字按照顺时针螺旋的形式填入其中。
例如:输入数字2,则程序输出:
1 2
4 3
输入数字3,则程序输出:
1 2 3
8 9 4
7 6 5
输入数字4,则程序输出:
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
思路:
1. 根据输入的数 n 创建 n * n 的二维数组
2. 数组内的数为:1,2,3,......,n * n;
因为数字排序为回字形向内,所以数组(0,0)位置的数是末尾的数,即最大的数;
我们可以创建一个int型数,如int num = n * n; 使其自减来实现数字的填充。
3. 确定循环条件及终止条件;
我考虑的是剥洋葱形式,即一层一层的进行,循环条件及终止条件也就是回字形的个数。每一层的起始位置就是对角线元素位置,所以次数 = n / 2; 但是因为 / 是向下取整,所以当 n 为奇数时,要 +1,防止最内层没有赋值。
4. 按回字形赋值
按右下左上的顺序一一赋值,此处就可以设置两个“指针”:i, j,固定其中一个不变改变另一个。
此处细节较多,比如向右赋值结束时,列标会超出维度;向下转弯时,行标要 +1,否则会覆盖上次赋值;
补充:添加转弯判断条件
此错误是在多次检验后发现的:对于奇数最内层,按最初想法,赋值完成后就结束,但是思路4中为了防止出错而修改的行列标会导致最内层赋2次值,即右(执行),下(不执行),左(不执行),上(执行)。
为了防止这种错误,同时为了使算法可以拓展到任意形状的矩阵,我们添加转弯判断条件,即当需要转弯时,判断其下一行/列是否已经赋值过。
具体细节请查看代码部分。
Java代码如下:
import java.util.Arrays;
public class work2 {
public static void main(String[] args) {
// int n = 11;// n维方阵
int m = 6;// 行
int n = 4;// 列
int[][] arr = new int[m][n];// 创建二维数组
int num = m * n;
int temp;
if (m % 2 == 0) {
temp = m / 2;
} else {
temp = m / 2 + 1;
}
for (int k = 0; k < temp; k++) {//回字数
int i = k;
int j = k;//出发坐标
if (j < n - k) {//转弯判断,共4次
while (j < n - k) {//→
arr[i][j++] = num--;
}
i++;
j--;
if (i < m - k) {
while (i < m - k) {//↓
arr[i++][j] = num--;
}
i--;
j--;
if (j > k - 1) {
while (j > k - 1) {//←
arr[i][j--] = num--;
}
i--;
j++;
if (i > k) {
while (i > k) {//↑
arr[i--][j] = num--;
}
}
}
}
}
}
for (int[] i : arr) {
for (int j : i) {
System.out.print(j + " \t");
}
System.out.println();
}
}
}