螺旋矩阵II
题目:https://leetcode-cn.com/problems/spiral-matrix-ii/
给定一个正整数 n,生成一个包含 1 到
n
2
n^2
n2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
示例:
输入: 3 输出: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ]
当 num <= tar 时,始终按照 从左到右 从上到下 从右到左 从下到上 填入顺序循环,每次填入后:
执行 num += 1:得到下一个需要填入的数字;
更新边界:例如从左到右填完后,上边界 t += 1,相当于上边界向内缩 1。
使用num <= tar而不是l < r || t < b作为迭代条件,是为了解决当n为奇数时,矩阵中心数字无法在迭代过程中被填充的问题。
public int[][] generateMatrix(int n) {
int[][] arr = new int[n][n];
//从左到右(0->n-1)
int left = 0;
int right = n-1;
//从上到下
int t = 0;
int b = n-1;
int num=1, target=n*n;
while (num<=target){
// 填充矩阵的上边,从左到右填充一行
// 每次循环行不变,列加一。并且循环结束后行加一
for (int i = left; i <= right; i++) { arr[t][i] = num++;}
t++; //自增后,下面就从(1,right)开始
// 填充矩阵的右边,从上到下填充一列
// 每次循环列不变,行加一。并且循环结束后列减一
for (int i = t; i <= b; i++) {arr[i][right] = num++;} //从上到下
right--;
// 填充矩阵下边,从右到左填充一行(注意只有一行的情况)
// 每次循环行不变,列减一。并且循环结束后行加一
for (int i = right; i >= left; i--) {arr[b][i] = num++;}//从右到左
b--;
// 填充矩阵左边,从下到上填充一列(注意只有一列的情况)
// 每次循环列不变,行加一。并且循环结束后列加一
for (int i = b; i >= t; i--) {arr[i][left] = num++;} //从下到上
left++;
}
return arr;
}
上文的代码太过巧妙,以至于我们t++一行,就实现了第二次绕+完成边界是<还是<=的问题。下文来实际考虑边界问题。
我们每画一条边都要坚持一致的左闭右开,或者左开又闭的原则,这样这一圈才能按照统一的规则画下来。
对应的代码实现
i,j,offset用于确定填充边界;而X,Y则是普普通通的,每轮循环+1。
public int[][] generateMatrix(int n) {
int[][] res = new int[n][n];
// 循环次数
int loop = n / 2;
// 定义每次循环起始位置
int startX = 0;
int startY = 0;
// 定义偏移量
int offset = 1;
// 定义填充数字
int count = 1;
// 定义中间位置
int mid = n / 2;
while (loop > 0) {
int i = startX;
int j = startY;
// 模拟上侧从左到右
for (; j< n -offset; ++j) {
res[startX][j] = count++;
}
// 模拟右侧从上到下
for (; i< n -offset; ++i) {
res[i][j] = count++;
}
// 模拟下侧从右到左
for (; j > startY; j--) {
res[i][j] = count++;
}
// 模拟左侧从下到上
for (; i > startX; i--) {
res[i][j] = count++;
}
loop--;
startX += 1;
startY += 1;
offset += 1;
}
if (n % 2 == 1) {
res[mid][mid] = count;
}
return res;
}
参考作者:jyd
链接:https://leetcode-cn.com/problems/spiral-matrix-ii/solution/spiral-matrix-ii-mo-ni-fa-she-ding-bian-jie-qing-x/