给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
要打印出顺时针的螺旋矩阵,就是模拟转圈的过程,从左到右填充上行,从上到下填充右列,从右到左填充下行,从下到上填充左列。这样的话每行每列的边界条件就很多,这里就要用到二分法里面的循环不变量原则,矩阵的每条边都坚持左闭右开或者左闭右闭的原则。
这里用左闭右开的原则遍历矩阵的每一条边,这样遍历每一条边的时候,只处理第一个节点,最后一个节点不处理,这个节点作为下一条边的起始位置。
class Solution {
public int[][] generateMatrix(int n) { // n 表示返回一个 n*n 的螺旋矩阵
int loop = 0; // 循环次数
int[][] res = new int[n][n]; // 循环后的矩阵
int start = 0; // 每次循环的开始点(start, start)
int count = 1; // 定义填充数字
int i, j; // i是纵向遍历的坐标 j是横向遍历的坐标 [i,j]
while (loop++ < n / 2) { // 循环可以转 n/2 圈
// 上边从左到右
for (j = start; j < n - loop; j++) { // j 起始位置为0
res[start][j] = count++; // 上边的 i 还是0,j 是本次循环的数值
}
// 右边从上到下
for (i = start; i < n - loop; i++) { // i 起始位置为0
res[i][j] = count++; // 右边的 i 是本次循环的数值,j 是上边循环过后的数值
}
// 下边从右到左
for (; j >= loop; j--) { // j 起始位置为上边循环过后的数值
res[i][j] = count++; // 下边的 i 是右边循环过后的数值,j 是本次循环的数值
}
// 左边从下到上
for (; i >= loop; i--) { // i 起始位置为右边循环过后的数值
res[i][j] = count++; // 左边的 i 是本次循环的数值,j 是下边循环过后的数值
}
start++; //循环完一圈,起始位置加一
}
if (n % 2 == 1) { // 如果 n 是奇数
res[start][start] = count; // 最后遍历出的值直接赋给数组
}
return res; // 返回数组
}
}