题目(力扣第59题)
给定一个正整数 n,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
示例:
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
分析
1、此题不涉及到什么算法,就是考察对代码的掌控,如何一步一步画出这个矩阵。
首先无论n为多少,结果都是一个方阵,所以我们在写的时候可以想象成多个环套在一起,我们需要从最外部的环开始,一直到最内部的环。
在画每个环时,从左到右,从上到下,从右到左,从下到上,需要不同的循环单独处理;一个环结束,要进入下一层。
四个方向的循环,我们要坚持循环不变量原则,也就是说如下方式:
每个方向的循环都结束于相同的位置,该行的倒数第二个(图1),尾元素归属下一个方向的循环。图3会导致混乱!
例如:从(0,0)位置开始,最外层,从左到右填充的代码为:
//当前位置
int i = 0, j = 0;
//循环次数
int loop = n==1?1:n-1;
//当前填充的数据
int count = 1;
//标识方向
int direction = 1;
//存放结果
int[][] result = new int[n][n];
while (count <= n * n) {
//从左往右 direction=1
if (direction == 1) {
for (int k = 0; k < loop; ++k) {
//设置值后向右移动,同时count自增1
result[i][j++] = count++;
}
//改变方向,使下次进入从上往下的循环
direction = 2;
//结束该次循环
continue;
}
//从上往下 direction=2
//.....
}
2、接下来是确定每层每个边循环的次数 loop:
n | 第一层loop值 | 第二层loop值 | 第三层loop值 | 第四层loop值 |
---|---|---|---|---|
3 | 2 | 1 | ||
4 | 3 | 1 | ||
5 | 4 | 2 | 1 | |
6 | 5 | 3 | 1 | |
7 | 6 | 4 | 2 | 1 |
- 由代码可知,
loop
值为循环控制变量; - 我们可以观察到,第一层的loop值,就是初始loop值取决于n的大小,如果n=1,则
loop=1
,否则loop=n-1
; - 但是如果当前loop值为2或3,则下一层的loop值一定为1;否则下一层的loop值为loop-2,每一层的各个方向loop值相等;
- 所以在每一层的最后一个方向,也就是从下往上赋值结束后,要修改loop;规则参考上述第三点;
3、每一层结束后,都要进入下一层,此时 i,j的值需要重新调整
完整代码及测试
/**
* question: 给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且
* 元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
*/
public class _59_SpiralMatrix2 {
public static void main(String[] args) {
printMatrix(generateMatrix(1));
}
public static int[][] generateMatrix(int n) {
//当前位置
int i = 0, j = 0;
//循环次数
int loop = n == 1 ? 1 : n - 1;
//当前填充的数据
int count = 1;
//标识方向
int direction = 1;
//存放结果
int[][] result = new int[n][n];
while (count <= n * n) {
//从左往右
if (direction == 1) {
for (int k = 0; k < loop; ++k) {
//设置值后向右移动,同时count自增1
result[i][j++] = count++;
}
//改变方向,使下次进入从上往下的循环
direction = 2;
//结束该次循环
continue;
}
//从上往下
if (direction == 2) {
for (int k = 0; k < loop; k++) {
result[i++][j] = count++;
}
direction = 3;
continue;
}
//从右往左
if (direction == 3) {
for (int k = 0; k < loop; k++) {
result[i][j--] = count++;
}
direction = 4;
continue;
}
//从下往上
if (direction == 4) {
for (int k = 0; k < loop; k++) {
result[i--][j] = count++;
}
//方向回到 左----》右
direction = 1;
//当前层结束,调整loop
loop = loop == 3 || loop == 2 ? loop / 2 : loop - 2;
//i,j指向下一层首个元素
i++;
j++;
continue;
}
}
return result;
}
/**
* 打印矩阵
*
* @param matrix
*/
public static void printMatrix(int[][] matrix) {
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j] + "\t");
}
System.out.println();
}
}
}