给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
关于本题给出两种方法解决:
第一种比较通俗易懂,
第二种则相对麻烦一些,但更具有深度。
首先第一种方法:
这种方法不需要记录已经走过的路径,所以执行用时和内存消耗都相对较小
首先设定上下左右边界 其次向右移动到最右,此时第一行因为已经使用过了,可以将其从图中删去,体现在代码中就是重新定义上边界
判断若重新定义后,上下边界交错,表明螺旋矩阵遍历结束,跳出循环,返回答案
若上下边界不交错,则遍历还未结束,接着向下向左向上移动,操作过程与第一,二步同理 不断循环以上步骤,直到某两条边界交错,跳出循环,返回答案
// 第一种方法
class solution {
public:
vector<int> result(vector<vector<int>>& matrix) {
int left = 0, up = 0;
int right = matrix.size()-1;
int down = matrix[0].size() - 1;//定义边界
vector<int> stk;
while (true) {
for (int i = left; i <= right; i++) {//向右移动直到最右
stk.push_back(matrix[up][i]);
}
if (++up> down)break;//重新设定上边界,若上边界大于下边界,则遍历遍历完成,下同
for(int i = up; i <= down; i++) {//向下
stk.push_back(matrix[i][right]);
}
if (--right <left)break;
for (int i = right; i >= left; i--) {//向左
stk.push_back(matrix[down][i]);
}
if (--down <up)break;
for (int i = down; i >=up; i--) {//向上
stk.push_back(matrix[i][left]);
}
if (++left > right)break;
}
return stk;
}
};
第二种方法:
首先定义一个顺时针旋转方向矩阵,directions[4][2] = { {0, 1}, {1, 0}, {0, -1}, {-1, 0} },根据上面directions定义,第一列值分别表示行的变化,1代表行往下移加1,-1表示往上移,同样第二列代表了列的变化,0表示不变,那我们是不是可以理解从{0,1}(行不变列右移)向{1, 0}(列不变,行下移)的过渡就是代表右转了呢。
具体原理:可以模拟螺旋矩阵的路径。初始位置是矩阵的左上角,初始方向是向右,当路径超出界限或者进入之前访问过的位置时,顺时针旋转,进入下一个方向。
判断路径是否进入之前访问过的位置需要使用一个与输入矩阵大小相同的辅助矩阵
stk2[row][column] ,其中的每个元素表示该位置是否被访问过。当一个元素被访问时,将
stk2[row][column] ==true,表示对应位置的元素设为已访问。如何判断路径是否结束?由于矩阵中的每个元素都被访问一次,因此路径的长度即为矩阵中的元素数量,当路径的长度达到矩阵中的元素数量时即为完整路径,将该路径返回。
// 第二种方法
class Solution {
public:
static constexpr int directions[4][2] = { {0, 1}, {1, 0}, {0, -1}, {-1, 0} };/
vector<int> result(vector<vector<int>>& matrix) {
int row = 0, column = 0;
int rows = matrix.size(), columns = matrix[0].size();
vector<int> stk1(rows * columns);//最终结果存放地方
vector<vector<bool>> stk2;//记录被读取过的值
stk2 = vector<vector<bool>>(rows, vector<bool>(columns, false));
if (matrix.size() == 0 || matrix[0].size() == 0) {
return {};
}
int dirindex = 0;
for (int i = 0; i < rows * columns; i++) {
stk1[i] = matrix[row][column];
stk2[row][column] = true;
int nextrow = row + directions[dirindex][0], nextcolumn = column + directions[dirindex][1];
if (nextrow < 0 || nextrow >= rows || nextcolumn < 0 || nextcolumn >= columns || stk2[nextrow][nextcolumn]) {//防止越界
dirindex = (dirindex + 1) % 4;//一旦越界则立马转弯
}
row = row + directions[dirindex][0];//更新下一次读取的值
column = column + directions[dirindex][1];
}
return stk1;
}
};
//测试用例
int main()
{
vector<vector<int>> matrix = { {1, 2, 3} ,{4, 5, 6},{7, 8, 9} };
solution *x = new solution;
Solution *y = new Solution;
vector<int> stk1;
vector<int> stk2;
stk1= x->result(matrix);
stk2 = y->result(matrix);
for (int i = 0; i < stk1.size(); i++) {
cout << stk1[i] <<stk2[i]<< endl;
}
}
测试结果