思路
按照要求,设置初始位置为(0,0),然后通过从左往右,从上到下,从右往左,从下到上的模拟方法生成矩阵。
细节
-
闭开的原则什么??
因为要实现4次循环,所以我们要规定区间的闭开原则,否则会因为区间的闭开原则不一致导致漏掉某些数据。这里我们选择左闭又开[x,y)。
-
特殊情况有木有??
对于n为奇数的情况,矩阵中心要单独赋值。矩阵中心的位置为(n/2,n/2).比如n=3。矩阵中心(1,1).
1 2 3 8 9 4 7 6 5
3.怎么根据n判断有几层螺旋圈?
这里我只能列举了,最后发现是有n/2次循环。 (1,0)(2,1)(3,1),(4,2)(5,2)…到最后其实发现,n每逢一个偶数加 一次螺旋圈。!!这不就是等差数列嘛。所以 最后就是n/2啦。
4.每层螺旋圈后,初始位置和每个循环的结束位置怎么更新?
对于起始位置(beginRow,beginCol),会发现他们其实是在斜对角线上。所以进入下一个螺旋圈前分别+1 即可。
对于循环结束位置。这里需要增设一个变量offset,用来控制结束位置更新。那怎么根据n和(beginRow或者 beginCol)更新呢?
因为每次进入下一个圈,访问的数目减少。最后要让结束位置<n+beginRow(or beginCol)-offset即可。那么 offset要做什么变化呢?n每逢一个偶数加一次螺旋圈,假设n=6,则一圈完后其实是n=4的情况。这里可以分 析,由于左闭右开的原则,n=6时,访问5个,进入第二圈(也就是n=4)访问3个,可知,每次访问的数目是 减去2的。所以对于offset来说,每次加2就可以了。因为这里我考虑的是相对情况,考虑绝对情况的话那当然 要加上起始位置的值啦。
如果没听懂,那还是列举吧。每圈结束位置的绝对位置是-1的.n=6时有3圈。
n | beginRow | offset | 结束位置<x |
---|---|---|---|
6 | 0 | 1 | 5(x的值) |
6 | 1 | 3 | 4(x的值) |
6 | 2 | 5 | 3(x的值) |
可以很容易推出offset是每次加2的。
vector<vector<int>>ans(n,vector<int>(n,0));//声明一个n*n的值全为0的二维矩阵。
int beginRow=0,beginCol=0;//row行,Col列;
int loop=n/2;
int mid=n/2;
int count=1;//用来给每个内容块赋值
int i,j;
int offset=1;//初始设为1,第一圈是1
while(loop--){
i=beginRow;
j=beginCol;
//从左往右,因为是横向遍历,所以需要改变j
for(j=beginCol;j<beginRow+n-offset;j++){
ans[beginRow][j]=count++;
}
//从上往下
for(i=beginRow;i<beginCol+n-offser;i++){
ans[i][j]=count++;
}
//从右往左
for(;j>beginCol;j--){
ans[i][j]=count++;
}
//从小往上
for(;i>beginRow;i--){
ans[i][j]=count++;
}
beginRow++;
beginCol++;
//
offset+=2;
if(n%2){
ans[mid][mid]=count;
}
}
return ans;
举一反三(逆时针螺旋)
vector<vector<int>>ans(n,vector<int>(n,0));
int beginRow=0,beginCol=0;
int loop=n/2;
int mid=n/2;
int offset=1;
int count=1;
int i,j;
//定义左闭右开
while(loop--){
i=beginRow;
j=beginCol;
//从上到下
for(i=beginRow;i<n+beginRow-offset;i++){
ans[i][beginCol]=count++;
}
//从左到右
for(j=beginCol;j<n+beginCol-offset;j++){
ans[i][j]=count++;
}
//从下到上
for(;i>beginRow;i--){
ans[i][j]=count++;
}
//从右到左
for(;j>beginCol;j--){
ans[i][j]=count++;
}
beginRow++;
beginCol++;
//控制遍历次数
offset+=2;
}
if(n%2){
ans[mid][mid]=count;
}
return ans;
运行结果: