思路:这道题其实并没有遇到特别高大上的算法,只是考察了我们的数组的下标和数学规律的发现。我们可以观察到,如果n=3时,这个矩阵实际上只有两圈,一个外圈由1,2,3,4,5,6,7,8构成。一个内圈是9,当n=4时,我们手写一下就知道,还是两圈,外圈是1,2,3,4,5,6,7,8,9 ,10,11,12,内圈是,13,14,15,16.当n=5时,就是三圈,n=6还是三圈。那么我们就发现规律了。我们控制圈数为n/2,然后如果n为奇数的话,最后处理那个最中间的数即可,n要是偶数的话,就不用管了,直接填好数组了。那么外层循环的循环次数就是n/2次。接下来看内层循环。
内层循环的作用就是填写具体的数字,我们根据数学规律可以发现,内层循环的最多次数是4*(n-1-i*2),i就是外层循环的当前循环次数,定义j为内存循环的变量。然后我们分情况讨论
我们以n=3举例,
0<=j<n-1-i*2时,填写的数组就是1,2那部分,那么ret[i][i+j]=k;k++;
n-1-i*2<=j<2*(n-1-i*2)填写的就是3,4那部分,那么ret[i+j-(n-1-i*2)][n-1-i]=k;k++;
2*(n-1-i*2)<=j<3*(n-1-i*2),填写的就是5,6那部分,那么ret[n-1-i][3*(n-1-i*2)-j+i]=k;k++;
3*(n-1-i*2)<=j<4*(n-1-i*2)填写的就是7,8部分,那么ret[4*(n-1-i*2)-j+i][i]=k;k++;
由于3为奇数,所以ret[n/2][n/2]=n*n;
代码
vector<vector<int>> generateMatrix(int n) {
int i,j,k;
vector<vector<int>> ret(n,vector(n,0));
k=1;
for(i=0;i<n/2;i++)
{
for(j=0;j<4*(n-1-i*2);j++,k++)
{
if(j>=0&&j<n-1-i*2)
{
ret[i][j+i]=k;
}
else if(j>=n-1-i*2&&j<2*(n-1-i*2))
{
ret[i+j-(n-1-i*2)][n-1-i]=k;
}
else if(j>=2*(n-1-i*2)&&j<3*(n-1-i*2))
{
ret[n-1-i][3*(n-1-i*2)-j+i]=k;
}
else if(j>=3*(n-1-i*2)&&j<4*(n-1-i*2))
{
ret[4*(n-1-i*2)-j+i][i]=k;
}
}
}
if(n%2==1)ret[n/2][n/2]=n*n;
return ret;
}