59. 螺旋矩阵 II(C++)
题目
给定一个正整数 n,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
示例:
输入: 3
输出:
[
[ 1, 2, 3 ],
[ 8, 9, 4 ],
[ 7, 6, 5 ]
]
分析与题解
本题不涉及算法,只是模拟赋值的过程,十分考验对代码的观察能力。
模拟顺时针画矩阵的过程:
- 填充上行从左到右
- 填充右列从上到下
- 填充下行从右到左
- 填充左列从下到上
由外向内一圈一圈这么画下去。
这里每一种颜色,代表一条边,我们遍历的长度,可以看出每一个拐角处的处理规则,拐角处让给新的一条边来继续画。本质是坚持了每条边左闭右开的原则。
完整代码如下:
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
// 初始化为全0数组
vector<vector<int>> res(n, vector<int>(n, 0));
// 奇偶的区别在于奇数边界需要单独赋值
int loop = n / 2;
int mid = n / 2;
// 每一圈循环控制边的长度
int offset = 1;
// 进行值的计数
int count = 1;
int startX = 0, startY = 0;
while (loop) {
int i = startX;
int j = startY;
// 先进行左上到右上的填充
for (j = startY; j < startY + n - offset; j++) {
res[startX][j] = count++;
}
// 再进行右上到右下的填充
// 列j此时退出循环的值正好为边界列
for (i = startX; i < startX + n - offset; i++) {
res[i][j] = count++;
}
// 再从右下到左下
for ( ; j > startY; j--) {
res[i][j] = count++;
}
// 再遍历左下到左上
for ( ; i > startX; i--) {
res[i][j] = count++;
}
// 更新初始点的位置
startX++;
startY++;
loop--;
// 上下左右各有宽度1的padding
// 所以每边赋值宽度减少2
offset += 2;
}
// 对于奇数,需要额外对中心点进行赋值
if (n % 2 == 1)
res[mid][mid] = n * n;
return res;
}
};