Spiral Matrix(螺旋矩阵)
题目 / Problem
中文: 给定一个 m × n 的矩阵 matrix,按照顺时针螺旋顺序返回矩阵中的所有元素。
English: Given an m × n matrix, return all elements of the matrix in clockwise spiral order.
示例 / Examples
Example 1
Input: matrix = [[1,2,3],[4,5,6],[7,8,9]]
Output: [1,2,3,6,9,8,7,4,5]
Example 2
Input: matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
Output: [1,2,3,4,8,12,11,10,9,5,6,7]
外层遍历结束后,继续遍历内部剩余的一行 [6,7]。
After traversing the outer layer, continue with the remaining inner row [6,7].
约束 / Constraints
m === matrix.lengthn === matrix[i].length1 <= m, n <= 10-100 <= matrix[i][j] <= 100
解题思路:四个边界 / Approach: Four Boundaries
使用四个变量表示当前还没有访问的矩形区域:
Use four variables to describe the unvisited rectangular region:
top = 最上方行下标 / topmost row index
bottom = 最下方行下标 / bottommost row index
left = 最左侧列下标 / leftmost column index
right = 最右侧列下标 / rightmost column index
每一轮按照四个方向访问最外层:
In each round, traverse the outermost layer in four directions:
- 从左到右访问顶部一行。
Traverse the top row from left to right. - 从上到下访问右侧一列。
Traverse the right column from top to bottom. - 从右到左访问底部一行。
Traverse the bottom row from right to left. - 从下到上访问左侧一列。
Traverse the left column from bottom to top.
访问完一条边后立即向内收缩对应边界:
After traversing one edge, immediately move that boundary inward:
top++
right--
bottom--
left++
边界变化 / Boundary Shrinking
初始区域 / Initial region
top
↓
┌───────────────┐
│ │
│ │
│ │
└───────────────┘
↑ ↑
bottom right
left →
访问外层后 / After the outer layer
┌───────┐
│ │
└───────┘
剩余区域 / Remaining region
只要满足 top <= bottom && left <= right,就仍然存在未访问元素。
Unvisited elements remain as long as top <= bottom && left <= right.
防止重复访问 / Preventing Duplicate Visits
访问顶部和右侧之后,剩余区域可能已经为空。例如矩阵最终可能只剩一行或一列。
After traversing the top and right edges, the remaining region may already be empty—for example, when only one row or one column remains.
因此,访问底部和左侧前必须再次检查边界:
Therefore, check the boundaries again before traversing the bottom and left edges:
if (top <= bottom) {
// 遍历底部 / Traverse bottom
}
if (left <= right) {
// 遍历左侧 / Traverse left
}
这两个检查可以防止单行或单列被读取两次。
These checks prevent a remaining single row or column from being visited twice.
JavaScript 实现 / JavaScript Implementation
/**
* @param {number[][]} matrix
* @return {number[]}
*/
function spiralOrder(matrix) {
const result = [];
let top = 0;
let bottom = matrix.length - 1;
let left = 0;
let right = matrix[0].length - 1;
while (top <= bottom && left <= right) {
// 1. 从左到右 / Left to right
for (let column = left; column <= right; column++) {
result.push(matrix[top][column]);
}
top++;
// 2. 从上到下 / Top to bottom
for (let row = top; row <= bottom; row++) {
result.push(matrix[row][right]);
}
right--;
// 3. 从右到左 / Right to left
if (top <= bottom) {
for (let column = right; column >= left; column--) {
result.push(matrix[bottom][column]);
}
bottom--;
}
// 4. 从下到上 / Bottom to top
if (left <= right) {
for (let row = bottom; row >= top; row--) {
result.push(matrix[row][left]);
}
left++;
}
}
return result;
}
执行过程 / Walkthrough
以 Example 1 为例:
For Example 1:
matrix =
[
[1,2,3],
[4,5,6],
[7,8,9]
]
第一层 / First Layer
| 方向 / Direction | 访问元素 / Elements | 结果 / Result |
|---|---|---|
| 左 → 右 / Left → Right | 1,2,3 | [1,2,3] |
| 上 → 下 / Top → Bottom | 6,9 | [1,2,3,6,9] |
| 右 → 左 / Right → Left | 8,7 | [1,2,3,6,9,8,7] |
| 下 → 上 / Bottom → Top | 4 | [1,2,3,6,9,8,7,4] |
边界向内收缩后,只剩中心元素 5。
After shrinking the boundaries, only the center element 5 remains.
第二层 / Second Layer
从左到右访问中心行,加入 5:
Traverse the center row from left to right and append 5:
[1,2,3,6,9,8,7,4,5]
特殊形状 / Special Shapes
单行矩阵 / Single Row
[[1,2,3,4]] → [1,2,3,4]
顶部遍历后 top > bottom,底部遍历会被跳过。
After the top traversal, top > bottom, so the bottom traversal is skipped.
单列矩阵 / Single Column
[[1],[2],[3]] → [1,2,3]
顶部访问 1,右侧继续访问 2,3。之后 left > right,左侧遍历会被跳过。
The top traversal visits 1, and the right traversal visits 2,3. Then left > right, so the left traversal is skipped.
非正方形矩阵 / Rectangular Matrix
算法只依赖独立的行、列边界,因此同样适用于 m !== n 的矩阵。
Because row and column boundaries are tracked independently, the algorithm also works when m !== n.
复杂度 / Complexity
矩阵共有 m × n 个元素,每个元素恰好访问一次。
The matrix contains m × n elements, and each element is visited exactly once.
- 时间复杂度 / Time:
O(m × n) - 辅助空间 / Auxiliary space:
O(1),不计算返回数组。O(1), excluding the returned array. - 结果空间 / Output space:
O(m × n)
易错点 / Common Pitfalls
- 每遍历完一条边,要立即收缩对应边界。
Shrink the corresponding boundary immediately after traversing an edge. - 访问底部一行前必须检查
top <= bottom。
Checktop <= bottombefore traversing the bottom row. - 访问左侧一列前必须检查
left <= right。
Checkleft <= rightbefore traversing the left column. - 四个方向的循环端点都包含在当前边界中,要注意使用
<=或>=。
Each direction includes its boundary endpoints, so use<=or>=carefully. - 不需要额外的
visited矩阵;四个边界已经能够保证每个元素只访问一次。
Novisitedmatrix is needed; the four boundaries already ensure each element is visited once.