【算法精讲】LeetCode 54. 螺旋矩阵:模拟遍历的艺术
摘要:本文详解 LeetCode 54 题“螺旋矩阵”,通过维护上下左右边界指针,按顺时针方向逐层遍历矩阵。每完成一圈收缩边界,直到所有元素被访问。时间 O(MN),空间 O(1)(不计输出),是模拟类题目的经典范式。
🧠 核心知识点:什么是“模拟法”?
在算法题中,“模拟法”指:
- 严格按照题目描述的规则或过程一步步执行。
- 不需要复杂的数据结构或数学推导,重在逻辑严谨和边界控制。
- 常用于矩阵遍历、路径搜索、状态机等问题。
对于二维矩阵的“螺旋遍历”,关键在于:
如何用变量控制当前遍历的方向和范围?
本题正是这一思想的绝佳实践 —— 我们用四个指针 top, bottom, left, right 来动态界定当前待遍历的“环形区域”。
🎯 题目引入:LeetCode 54. 螺旋矩阵
题目描述
给你一个 m x n 的矩阵 matrix,请按照 顺时针螺旋顺序,返回矩阵中的所有元素。
约束条件:
- 矩阵可能为空,也可能为单行/单列。
- 必须按“右→下→左→上”的顺序循环遍历,直到所有元素都被访问。
示例 1:
输入: matrix = [[1,2,3],
[4,5,6],
[7,8,9]]
输出: [1,2,3,6,9,8,7,4,5]
示例 2:
输入: matrix = [[1,2,3,4],
[5,6,7,8],
[9,10,11,12]]
输出: [1,2,3,4,8,12,11,10,9,5,6,7]
💡 解题思路详解
❗ 为什么不能简单用嵌套循环?
因为螺旋路径不是固定的矩形块,而是随着遍历不断“内缩”的环形结构。我们需要动态调整遍历范围。
✅ 正确做法:用四个边界指针 + 方向控制
🔍 关键洞察:像剥洋葱一样一层层遍历
我们可以这样做:
-
初始化四个边界指针:
top = 0,bottom = m - 1left = 0,right = n - 1
-
定义遍历方向顺序:
- 右 → 下 → 左 → 上 (循环)
-
每一圈分四步走:
- 从左到右遍历顶行 →
top++ - 从上到下遍历右列 →
right-- - 从右到左遍历底行(如果还有行)→
bottom-- - 从下到上遍历左列(如果还有列)→
left++
- 从左到右遍历顶行 →
-
终止条件:当
top > bottom或left > right时停止。
⚠️ 注意:第三步和第四步需要判断是否仍有有效行/列,避免重复遍历!
💻 代码实现与逐行解析
from typing import List
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
if not matrix or not matrix[0]:
return []
m, n = len(matrix), len(matrix[0])
result = []
top, bottom = 0, m - 1
left, right = 0, n - 1
while top <= bottom and left <= right:
# 1. 从左到右遍历顶行
for col in range(left, right + 1):
result.append(matrix[top][col])
top += 1
# 2. 从上到下遍历右列
for row in range(top, bottom + 1):
result.append(matrix[row][right])
right -= 1
# 3. 从右到左遍历底行(需检查是否还有行)
if top <= bottom:
for col in range(right, left - 1, -1):
result.append(matrix[bottom][col])
bottom -= 1
# 4. 从下到上遍历左列(需检查是否还有列)
if left <= right:
for row in range(bottom, top - 1, -1):
result.append(matrix[row][left])
left += 1
return result
📊 复杂度分析
- 空间复杂度: (不计输出数组)
仅使用了常数个变量(top,bottom,left,right,result是返回值,不算额外空间)。
✅ 若考虑输出数组,则空间为 ,但这是不可避免的,因为要返回所有元素。
⚠️ 易错点提醒
- 忘记判断第三步和第四步的有效性:可能导致重复添加元素或越界。
- 边界更新顺序错误:比如先更新
top再遍历右列,会导致漏掉角落元素。 - 空矩阵未处理:虽然题目一般保证非空,但健壮性代码应包含此判断。
🔄 对比其他解法
| 方法 | 时间复杂度 | 空间复杂度 | 是否易读 |
|---|---|---|---|
| 递归分层 | O(MN) | O(min(M,N)) | 较难 |
| 方向向量+visited | O(MN) | O(MN) | 中等 |
| 本题解法 | O(MN) | O(1) | 高 |
✅ 本题解法是面试最推荐写法,逻辑清晰、效率高、易于调试!