1. 题解
- 如果一条边从头遍历到底,则下一条边遍历的起点随之变化
- 选择不遍历到底,可以减小横向、竖向遍历之间的影响
- 一轮迭代结束时,4条边的两端同时收窄 1
- 一轮迭代所做的事情变得很清晰:遍历一个“圈”,遍历的范围收缩为内圈
- 一层层向里处理,按顺时针依次遍历:上、右、下、左。
- 不再形成“环”了,就会剩下:一行或一列,然后单独判断
矩阵不一定是方阵
top < bottom && left < right 是循环的条件
无法构成“环”了,就退出循环,退出时可能是这 3 种情况之一:
- top == bottom && left < right —— 剩一行
- top < bottom && left == right —— 剩一列
- top == bottom && left == right —— 剩一项(也算 一行/列)
处理剩下的单行或单列
因为是按顺时针推入结果数组的,所以
- 剩下的一行,从左至右 依次推入结果数组
- 剩下的一列,从上至下 依次推入结果数组
代码
每个元素访问一次,时间复杂度 O(m*n),m、n 分别是矩阵的行数和列数
2. 循环
class Solution {
public:
/*1. 坚持循环不变量原则,固定规则来遍历2.
*/vector<int> spiralOrder(vector<vector<int>>& matrix) {vector<int> res;if (matrix.empty()) {return res;}int top = 0;int bottom = matrix.size() - 1;int left = 0;int right = matrix[0].size() - 1;while (left < right && top < bottom) {// 更新顶行for (int i = left; i < right; i++) {res.push_back(matrix[top][i]);}// 更新最右列for (int i = top; i < bottom; i++) {res.push_back(matrix[i][right]);}// 更新最底行for (int i = right; i > left; i--) {res.push_back(matrix[bottom][i]);}// 更新左列for (int i = bottom; i > top; i--) {res.push_back(matrix[i][left]);}left++;top++;right--;bottom--;}if (top == bottom) {for (int i = left; i <= right; i++) {res.push_back(matrix[top][i]);}} else if (left == right) {for (int i = top; i <= bottom; i++) {res.push_back(matrix[i][left]);}}return res;}
};