顺时针打印螺旋矩阵
题目链接
打印矩阵最关键的地方在于控制方向和避免重复打印
许多题解用的二维矩阵来表示方向
本文章全篇不用额外矩阵来控制方向,而通过每次要转弯时的动作逻辑来控制
每次在转弯时,即碰到矩阵边界时,需要将下一个遍历方向前进一步,避免重复打印
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int> res;
int l=0,r=matrix[0].size()-1;
int t=0,b=matrix.size()-1;
while(1){
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(--r<l) break;
for(int i=r;i>=l;i--) res.push_back(matrix[b][i]);
if(--b<t) break;
for(int i=b;i>=t;i--) res.push_back(matrix[i][l]);
if(++l>r) break;
}
return res;
}
};
顺时针构造矩阵
题目链接
这题几乎与上题一模一样
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res(n,vector<int>(n,0));
int l=0,r=n-1;
int t=0,b=n-1;
int c=1;
while(1){
for(int i=l;i<=r;i++) res[t][i]=c++;
if(++t>b) break;
for(int i=t;i<=b;i++) res[i][r]=c++;
if(--r<l) break;
for(int i=r;i>=l;i--) res[b][i]=c++;
if(--b<t) break;
for(int i=b;i>=t;i--) res[i][l]=c++;
if(++l>r) break;
}
return res;
}
};
不定长步数的顺序打印矩阵坐标
题目链接
这个题目一定要发现,每次的步数有规律增加,即1,1,2,2,3,3…
我们可以通过扩展边界的方式来实现步数的变相增加,即每个方向走到规定边界时就要将那个方向的边界+1,这样下次再在这个方向遍历要走到尽头就要多走。
另外注意的是,循环逻辑中夺走了一步,因此每次循环一个方向完成时要在这个方向回退一步。
为了避免重复打印,要在走到边界时在下个要遍历的方向先走一步。
class Solution {
bool isValid(int x,int y,int rows,int cols){
if(x>=0&&x<rows&&y>=0&&y<cols) return true;
return false;
}
public:
vector<vector<int>> spiralMatrixIII(int rows, int cols, int rStart, int cStart) {
vector<vector<int>> res;
int x=rStart,y=cStart,num=0;
int l=cStart-1,r=cStart+1,t=rStart-1,b=rStart+1;
while(num<rows*cols){
while(y<=r){
if(isValid(x,y,rows,cols)){
res.push_back({x,y});
num++;
}
y++;
}
y--;r++;x++;
while(x<=b){
if(isValid(x,y,rows,cols)){
res.push_back({x,y});
num++;
}
x++;
}
x--;b++;y--;
while(y>=l){
if(isValid(x,y,rows,cols)){
res.push_back({x,y});
num++;
}
y--;
}
y++;l--;x--;
while(x>=t){
if(isValid(x,y,rows,cols)){
res.push_back({x,y});
num++;
}
x--;
}
x++;t--;y++;
}
return res;
}
};