例题 螺旋矩阵
给你一个正整数,生成一个包含1到所有元素,且元素按顺时针顺序螺旋排列的 正方形矩阵
matrix
。
模拟图像的原则:循环不变量。比如在填充该矩阵的第一行时,填充的范围是[0,n-2],那么在填充它接下来的一列时,填充范围也是[0,n-2]。
步骤:
我们先确定填充数组的方式——循环遍历每一圈。
循环的圈数-->当n=偶数时,循环n/2圈;当n=奇数时,我们依然可以循环n/2圈,再对剩下的、位于数组中心的元素赋值即可。
在循环过程中,每一圈的 i,j 起始位置会发生变化,所以我们用两个变量 startx,starty 作为 每次循环 i,j 的落脚点。而 i,j 在不同圈中的终止位置也不同,可以用一个变量 endxy 表示,每一圈下来都减1。
code:
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res(n,vector<int>(n));
int count=1;//填充数
int startx = 0, starty = 0;//每一圈的起始位置
int endxy=n-1;//每一圈的结束位置
int loop = n/2;
while(loop--)//填充每一圈
{
int i,j;
for(j=starty; j<endxy; j++)
res[startx][j] = count++;
for(i=startx; i<endxy; i++)
res[i][j] = count++;
for(; j>starty; j--)
res[i][j] = count++;
for(; i>startx; i--)
res[i][j]=count++;
startx++;
starty++;
endxy--;//右边缩短一个单位
}
if(n%2 == 1)//是奇数矩阵
res[n/2][n/2] = count;
return res;
}
};
例题2: 螺旋矩阵
给你一个 m
行 n
列的矩阵 matrix
,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
这一题跟例题相似,都是遍历螺旋矩阵。
但不同的是,此题的 m ≠ n,单纯判断圈数、设置起始位置终止已经不好使了。(比如矩阵为4x3时,循环不变量在第二圈失效)
这题的思想是,既然无法控制循环不变量,那我们每一行、每一列都遍历到底,重叠访问的矩阵元素,我们不要push_back入向量的下一个元素,push_back在上一个重合的元素即可。
在遍历矩阵的过程中,我们每遍历完一行、一列(边界收缩),就将这一行、一列从原矩阵中消除掉(逻辑上),逐渐消除成只剩一行或一列(边界相遇)。
code:
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
if (matrix.empty()) return {};
int l = 0, r = matrix[0].size() - 1, t = 0, b = matrix.size() - 1;
vector<int> res;
while(1)
{//for循环都 <= 终止位置,使res数组里的数可以重合
for(int i = l; i <= r; i++) res.push_back(matrix[t][i]);
if(++t > b) break;//只有一层 退出
for(int i = t; i <= b; i++) res.push_back(matrix[i][r]);
if(l > --r) break;//只有一列
for(int i = r; i >= l; i--) res.push_back(matrix[b][i]);
if(t > --b) break;//削减后只有一层了
for(int i = b; i >= t; i--) res.push_back(matrix[i][l]);
//if(l > --r) break;//削减后只有一列了
if(++l > r) break;
}
return res;
}
};