问题描述
螺旋矩阵是一道经典的数组操作题目。给定一个正整数n,生成一个包含1到n²所有元素的n×n螺旋矩阵。所谓螺旋矩阵,就是按照顺时针螺旋顺序,从外向内依次填入数字1到n²。
例如,当n=3时,生成的螺旋矩阵为:
1 2 3
8 9 4
7 6 5
题目链接
解题思路
解决螺旋矩阵问题的关键在于模拟螺旋填充的过程。我们可以将整个填充过程看作是一层一层向内的循环过程,每一层都是按照"右→下→左→上"的顺序填充数字。
具体步骤如下:
- 定义起始位置坐标(startX, startY),初始值为(0, 0)
- 定义偏移量offset,用于控制每条边的遍历长度
- 定义计数器count,从1开始,表示当前要填入的数字
- 创建一个n×n的二维数组res,用于存储结果
- 计算需要循环的圈数loop,为n/2(向下取整)
- 按照"右→下→左→上"的顺序填充数字
- 每完成一圈后,更新起始位置和偏移量
- 如果n为奇数,最后需要单独处理矩阵中心的元素
代码实现
javascript
var generateMatrix = function (n) {
let startX = 0; // 起始行坐标
let startY = 0; // 起始列坐标
let offset = 1; // 每圈遍历的长度减少量
let count = 1; // 当前填入的数字
let res = new Array(n).fill(0).map(() => new Array(n).fill(0)); // 创建n×n的二维数组
let loop = Math.floor(n / 2); // 需要循环的圈数
while (loop--) {
let i = startX, j = startY; // 当前位置
// 上边:从左到右
for (; j < n - offset; j++) {
res[i][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++;
}
// 更新起始位置
startX++;
startY++;
// 更新偏移量
offset += 1;
}
// 如果n为奇数,单独处理矩阵中心的元素
if (n % 2 == 1) {
let mid = Math.floor(n / 2);
res[mid][mid] = count;
}
return res;
};
算法分析
- 时间复杂度:O(n²),其中n是给定的矩阵大小。我们需要填充n²个元素。
- 空间复杂度:O(n²),需要创建一个n×n的二维数组来存储结果。
关键点解析
- 边界控制:通过offset变量控制每条边的遍历长度,确保不会重复填充。
- 方向转换:使用四个独立的循环分别处理四个方向的填充。
- 起始位置更新:每完成一圈后,起始位置向内移动一格。
- 中心元素处理:当n为奇数时,矩阵中心的元素需要单独处理。
总结
螺旋矩阵是一道很好的练习数组操作和边界条件处理的题目。解决这类问题的关键在于:
- 清晰地定义循环的边界条件
- 正确地更新循环变量
- 处理特殊情况(如矩阵中心元素)