给定一个正整数 n,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
示例:
输入: 3 输出: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ]
解析:
一个数组遍历问题,只是改变了遍历的方式。不是按行遍历,也不是按列遍历,而是螺旋遍历。只要考虑到这种遍历方式怎么进行就可以了。我的方法采用的比较简单,定义了一个同样大小的bool的二维数组,标记是否有数字填入。并按照向左,向右,向下,向上的顺序进行填数字。每次都要判断此处是否越界,是否填值。这种方法空间复杂度较高,而且要记得每次都更新bool标志。
代码:
vector<vector<int>> generateMatrix(int n)
{
vector<vector<int>>res(n, vector<int>(n, 0));
if (n == 0)
return res;
vector<vector<bool>>hasNum(n, vector<bool>(n, false));//标志数组
int i = 0, j = 0;
int num = 2;
res[0][0] = 1;//第一个数据
hasNum[0][0] = true;
while (true)
{
if ((i - 1 < 0 || hasNum[i - 1][j] == true)
&& (i + 1 > n - 1 || hasNum[i + 1][j] == true)
&& (j - 1 < 0 || hasNum[i][j - 1] == true)
&& (j + 1 > n - 1 || hasNum[i][j + 1] == true))//跳出循环的判断,上下左右都有值或越界
break;
while (j + 1 < n&&hasNum[i][j + 1] == false)//向右
{
res[i][j + 1] = num;
hasNum[i][j + 1] = true;//记得更新标记
++j;
++num;
}
while (i + 1 < n&&hasNum[i + 1][j] == false)//向下
{
res[i + 1][j] = num;
hasNum[i+1][j] = true;
++i;
++num;
}
while (j - 1 >= 0 && hasNum[i][j - 1] == false)//向左
{
res[i][j - 1] = num;
hasNum[i][j - 1] = true;
--j;
++num;
}
while (i - 1 >= 0 && hasNum[i - 1][j] == false)//向上
{
res[i - 1][j] = num;
hasNum[i-1][j] = true;
--i;
++num;
}
}
return res;
}
他山之石:
vector<vector<int>> generateMatrix(int n)
{
vector<vector<int>> res(n,vector<int>(n,0));
int c=(n+1)/2;//转的圈数
int p=n,q=n;//每次遍历的长度
int val=1;//填入的数据
for(int i=0;i<c;i++,p-=2,q-=2)//遍历一圈,行和列都减2
{
for(int col=i;col<i+q;col++)//向右
{
res[i][col]=val++;
}
for(int row=i+1;row<i+p;row++)//向下
{
res[row][i+q-1]=val++;
}
if(p==1 || q==1) break;//如果只剩一行或一列,则上面两个过程就遍历结束
for(int col=i+q-2;col>=i;col--)//向左
{
res[i+p-1][col]=val++;
}
for(int row=i+p-2;row>i;row--)向上
{
res[row][i]=val++;
}
}
return res;
}
两种方法的不同之处是,我用标志位来判断是否需要填数字或是否遍历结束。而他山之石采用的是计算出来每行或每列需要遍历的数字的个数。