54. 螺旋矩阵
4 min
题目
解法:边界收缩
思路
核心思想是通过边界收缩模拟螺旋路径。定义四个边界(上、下、左、右),按顺时针方向遍历边界元素后收缩对应边界,直到边界交错结束。
正确性在于:每次遍历完整条边界后,该边界即失效,收缩边界可确保内层元素形成新矩形。边界交错条件(top>bottom 或 left>right)能精确判断遍历完成,不会遗漏或重复访问元素。
- Step 1: 初始化边界 top=0, bottom=m-1, left=0, right=n-1
- Step 2: 从左到右遍历上边界,完成后 top++ 并检查边界
- Step 3: 从上到下遍历右边界,完成后 right— 并检查边界
- Step 4: 从右到左遍历下边界,完成后 bottom— 并检查边界
- Step 5: 从下到上遍历左边界,完成后 left++ 并检查边界
- Step 6: 循环执行 Step2-5 直到边界交错
复杂度
- 时间复杂度: ,每个元素被访问一次,m 和 n 分别为矩阵的行列数
- 空间复杂度: ,仅使用常数额外空间存储边界变量(结果数组不计入)
代码
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int> ans;
if (matrix.empty()) return ans;
int top = 0, bottom = matrix.size() - 1;
int left = 0, right = matrix[0].size() - 1;
while (true) {
// 1. 从左到右
for (int i = left; i <= right; ++i) ans.push_back(matrix[top][i]);
if (++top > bottom) break; // 上边界下移,如果越界则结束
// 2. 从上到下
for (int i = top; i <= bottom; ++i) ans.push_back(matrix[i][right]);
if (--right < left) break; // 右边界左移
// 3. 从右到左
for (int i = right; i >= left; --i) ans.push_back(matrix[bottom][i]);
if (--bottom < top) break; // 下边界上移
// 4. 从下到上
for (int i = bottom; i >= top; --i) ans.push_back(matrix[i][left]);
if (++left > right) break; // 左边界右移
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int> ans;
if (matrix.empty()) return ans;
int top = 0, bottom = matrix.size() - 1;
int left = 0, right = matrix[0].size() - 1;
while (true) {
// 1. 从左到右
for (int i = left; i <= right; ++i) ans.push_back(matrix[top][i]);
if (++top > bottom) break; // 上边界下移,如果越界则结束
// 2. 从上到下
for (int i = top; i <= bottom; ++i) ans.push_back(matrix[i][right]);
if (--right < left) break; // 右边界左移
// 3. 从右到左
for (int i = right; i >= left; --i) ans.push_back(matrix[bottom][i]);
if (--bottom < top) break; // 下边界上移
// 4. 从下到上
for (int i = bottom; i >= top; --i) ans.push_back(matrix[i][left]);
if (++left > right) break; // 左边界右移
}
return ans;
}
};