思路
本题最大的考察点在于对循环的控制,尤其是对边界的把握,即:上行从左到右,右列从上到下,下行从右到左,左列从下到上。
代码
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
//首先创建n行n列的矩阵,其元素赋值为0
vector<vector<int>> ret(n,vector<int>(n,0));
int stx = 0,sty = 0;//stx表示从哪行开始,sty表示从哪列开始
int loop = n/2; //loop代表要循环几次
int count = 1;//从1开始
int offset = 1;//循环控制变量
int i = 0;//控制行
int j = 0;//控制列
while(loop--)
{
//1.上行从左到右
for(j = sty;j<n-offset;j++)
{
ret[stx][j] = count++;
}
//2.右列从上到下
for(i = stx;i<n-offset;++i)
{
ret[i][j] = count++;
}
//3.下行从右到左
for(;j>offset-1;j--)
{
ret[i][j] = count++;
}
//4.左列从下到上
for(;i>offset-1;i--)
{
ret[i][j] = count++;
}
stx+=1;//开始行+1
sty+=1;//开始列+1
offset+=1;
}
if(n%2==1)//n为奇数时,补上最中间的点的值
{
ret[n/2][n/2] = count;
}
return ret;
}
};
代码细解
n为偶数时,以6*6的矩阵为例,每种颜色的线条都代表一次循环,对于拐角处的数值我们采用了左闭右开方式的处理(即拐角处的数值交由下一个边来遍历)。
从图中看很多问题迎刃而解
(1)为什么循环次数loop=n/2呢?
因为一次循环(红蓝绿黄一圈)会填两行和两列的值,故填满n行n列只需要循环n/2次。
这是有伙伴可能会有疑问,若是n为奇数呢,如果n为奇数的话,我们仍然只需要循环n/2次,这时候剩下的最中间的那个格子我们只需要补上其值就好了。
这里给出一张n=5的图,最后25的位置需要我们填充,可以自己试着画一画。
(2)对stx与sty,和offset的理解
从图中我们不难看出,我们需要控制循环的起始截止位置,以循环1为例,第一次循环j从0到4,第二次循环j从1到3,第三次循环从2到2,这样们只需要每次循环结束后将起始行stx和起始列sty分别+1,让offset每次循环结束后+1控制循环的截止位置。
//循环1的代码
for(j = sty;j<n-offset;j++)
{
ret[stx][j] = count++;
}
(3)n为奇数的情况
当n为奇数时,我们补上最中间的值
if(n%2==1)
{
ret[n/2][n/2] = count;
}