给你一个正整数 n
,生成一个包含 1
到 n2
所有元素,且元素按顺时针顺序螺旋排列的 n x n
正方形矩阵 matrix
。
示例 1:
输入:n = 3 输出:[[1,2,3],[8,9,4],[7,6,5]]
示例 2:
输入:n = 1 输出:[[1]]
思路:
要坚持循环不变量原则,每一条边,横纵遍历的方式要相同,头和尾要不要遍历要确定好,也就是开闭区间,模拟顺时针画矩阵的过程:
- 填充上行从左到右
- 填充右列从上到下
- 填充下行从右到左
- 填充左列从下到上
由外向内一圈一圈画下去,一圈遍历4次,圈数则代表最外层的循环 ,在里层每条边遍历时,要确定遍历的个数,也就是确定开闭区间,这里采用左闭右开的形式遍历每条边:
关键点则在于拐角处,由于左闭右开,拐角处均让给新的一条边继续画。
在遍历每条边时,要让其中的横或者纵坐标不变,另一个在不断更新。然后有一个很重要的一点,因为4条边要写4个for循环,第一个for循环从左往右最上面开始遍历,其他三个for循环都需要记一下上一次循环索引变量的值,例如最开始第一行从左到右,i=0,j从0变到1,把两个空填上,填完后由于j当前为1,比2小,因此继续加1变成j=2,这时已经不满足for循环条件,因此进入下一个for循环。第二个for循环的时候,从上往下遍历,j=2就成为了固定不变的值,i便不断更新,依次类推进入第三个循环,第四个循环,完成一圈遍历。
由于完成一圈遍历,会进行收缩,第一行和最后一列开始遍历的时候,行数和列数均下移了一位,因此要定义两个开始的横纵坐标值为0,这两个值只在一圈循环结束的时候进行更新,因此在内层循环遍历时,用i和j去移动,在循环最开始时把横纵坐标初始值赋值给i和j。
另外圈收缩,会影响区间的长度,因此每次循环结束时,要把区间长度进行更新减1.
最后,如果n是奇数,需要单独处理一下矩形中间值。
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res(n,vector<int>(n,0));
int border=1;
int i,j,count=0,startx=0,starty=0;
int loop=n/2;
while(loop)
{
i=startx;
j=starty;
for(j=startx;j<n-border;j++)
{
count++;
res[startx][j]=count;
}
for(i=starty;i<n-border;i++)
{
count++;
res[i][j]=count;
}
for(;j>startx;j--)
{
count++;
res[i][j]=count;
}
for(;i>starty;i--)
{
count++;
res[i][j]=count;
}
loop--;
border++;
startx++;
starty++;
}
if(n%2)
{
res[n/2][n/2]=n*n;
}
return res;
}
};