1 问题
给定一个正整数 n,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
示例:
输入: 3
输出:
[
[ 1, 2, 3 ],
[ 8, 9, 4 ],
[ 7, 6, 5 ]
]
2 解法
模拟顺时针画矩阵的过程:
填充上行从左到右
填充右列从上到下
填充下行从右到左
填充左列从下到上
由外向内一圈一圈这么画下去。
为了控制循环时的边界问题,采用循环不变量原则,始终坚持左闭右开原则(或左开右闭)。
这里每一种颜色,代表一条边,我们遍历的长度,可以看出每一个拐角处的处理规则,拐角处让给新的一条边来继续画。
这也是坚持了每条边左闭右开的原则。
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res(n, vector<int>(n, 0));
//定义每循环一圈的起始位置
int startX = 0;
int startY = 0;
//第几圈,如n为奇数3,那么loop = 1 只循环一圈,单独处理矩阵中间值
int loop = n / 2;
//控制每圈长度
int offset = 1;
//矩阵中间位置,如n=3,中间的位置是(1,1),n=5,中间位置为(2, 2)
int mid = n / 2;
//用来给矩阵中每一个空格赋值
int count = 1;
//控制循环圈数,从最外圈开始
while(loop--)
{
int i = startX;
int j = startY;
//遍历上边,从左至右,遵循左闭右开原则
for(;j < startY + n - offset; j++)
{
res[i][j] = count++;
}
//遍历右边,从上到下
for(; 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++;
//下一圈时,控制每条边遍历的长度(下一圈比上一圈需多减2)
offset += 2;
}
//如果n为基数,单独填充矩阵中间元素
if(n % 2)
{
res[mid][mid] = count;
}
return res;
}
};