54. 螺旋矩阵(中等)
Blind 75 › 54. 螺旋矩阵(中等) (第 2 章)
题目
给定一个 m 行 n 列的整数矩阵,从左上角出发:先向右走到右边界,再向下、向左、向上,贴着尚未访问的区域一圈一圈往里走,按访问顺序返回其中的所有元素。
自造示例:[[1,2,3],[4,5,6],[7,8,9],[10,11,12]] → [1,2,3,6,9,12,11,10,7,4,5,8]。
约束:m ≥ 1,n ≥ 1;元素值范围 -100 ~ 100。
思路
一句话:不要一个格子一个格子地“试走”,而是把螺旋看成一圈一圈剥掉外层的边,用四条边界表示当前未访问的矩形。
最直白的做法是“方向模拟”:定义上、右、下、左四个方向,每次走下一步前都判断“下一格是否越界、是否已经访问过”。这样能写,但需要一张 m × n 的访问表,且转向、停止条件都容易写错。
关键观察:螺旋的每一圈都是当前矩形的四条边——上边从左到右、右边从上到下、下边从右到左、左边从下到上。每剥完一条边,就把对应的边界向里收缩一格,剩下的仍是矩形,于是可以重复同样操作。
因此不需要维护“下一步怎么走”,只需要维护 top / bottom / left / right 四条边界,逐步收缩即可。唯一要小心的是:某些圈只剩一行或一列时,要把“下边、左边”的遍历保护起来,避免重复收录。
解法
维护四个边界 top, bottom, left, right,循环处理:
- 从左到右走
top行,然后top++。 - 从上到下走
right列,然后right--。 - 若
top ≤ bottom:从右到左走bottom行,然后bottom--。 - 若
left ≤ right:从下到上走left列,然后left++。
以自造示例看过程:
| 当前边界 | 本轮收集 | 收缩后边界 |
|---|---|---|
| top=0, bottom=3, left=0, right=2 | 上边 1,2,3;右边 6,9,12;下边 11,10;左边 7,4 | top=1, bottom=2, left=1, right=1 |
| top=1, bottom=2, left=1, right=1 | 上边 5;右边 8 | top=2, bottom=2, left=1, right=0 |
| top=2, bottom=2, left=1, right=0 | 已无未访问元素,循环结束 | — |
最终结果即 [1,2,3,6,9,12,11,10,7,4,5,8]。
下图把上面 4 个步骤串成流程,并逐步演示:


C++
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
int top = 0, bottom = matrix.size() - 1;
int left = 0, right = matrix[0].size() - 1;
vector<int> ans; while (top <= bottom && left <= right) {
// 上边:left → right
for (int j = left; j <= right; ++j) {
ans.push_back(matrix[top][j]);
}
++top; // 右边:top → bottom
for (int i = top; i <= bottom; ++i) {
ans.push_back(matrix[i][right]);
}
--right; // 只剩一行时,下边不能再走,否则会重复
if (top <= bottom) {
for (int j = right; j >= left; --j) {本篇为付费内容
您已阅读试读部分,购买后即可解锁全文。
⚠️ 本站内容已做唯一性标记并受版权保护,未经授权禁止转载,侵权必究。
还没有评论,来说两句?