Hot 100 --- 螺旋矩阵
本文概览:本文以LeetCode经典题目"螺旋矩阵"为例,重点讲解如何将螺旋遍历过程拆解为四条边的循环收缩,通过边界变量动态控制遍历范围和退出条件
一、题目

二、题目分析
给定一个 m×n 矩阵,按照顺时针螺旋顺序返回所有元素
目标:模拟从外圈到内圈的螺旋遍历过程
核心难点:这题没有暴力与优化的区分,唯一的解法就是模拟螺旋遍历。难点在于:
- 如何正确模拟这个遍历过程
- 如何找到退出条件
思路概览
Java实现代码如下
1 | public List<Integer> spiralOrder(int[][] matrix) { |
思路简要说明
四条边:将螺旋遍历拆解为四条边——顶层(左→右)、右层(上→下)、底层(右→左)、左层(下→上)
边界收缩:每遍历完一条边,对应的边界就往内缩一次(top++、right--、bottom--、left++)
退出条件:每次收缩后检查边界是否交叉,交叉说明遍历完毕
三、思路详解
螺旋遍历的本质
仔细观察螺旋遍历的过程,它其实就是一个不断"剥圈"的过程——每一圈由四条边组成,遍历完一圈后往内缩一圈,继续遍历下一圈
我们可以把每一圈拆解为四条边,按固定顺序遍历:
1 | ① 顶层:从左到右 →→→→→ |
用一个 4×5 的矩阵来直观感受:
1 | →→→→→ ← 顶层(第1条边) |
关键规律:每遍历完一条边,边界就收缩
遍历完顶层后,顶层已经走过了,下一次的顶层应该往下移一行(top++)
遍历完右层后,右层已经走过了,下一次的右层应该往左移一列(right--)
遍历完底层后,底层已经走过了,下一次的底层应该往上移一行(bottom--)
遍历完左层后,左层已经走过了,下一次的左层应该往右移一列(left++)
用图来表示边界的收缩过程:
初始状态:
1 | left right |
遍历顶层 1,2,3,4,5 后,top++:
1 | left right |
遍历右层 10,15,20 后,right--:
1 | left right |
遍历底层 19,18,17,16 后,bottom--:
1 | left right |
遍历左层 11,6 后,left++:
1 | left right |
此时进入内圈,继续重复四条边的遍历,直到边界交叉
退出条件
每次边界收缩后,需要检查边界是否交叉:
top > bottom:顶层超过了底层,说明纵向没有剩余行right < left:右层超过了左层,说明横向没有剩余列
只要出现任意一种交叉,就说明所有元素已经遍历完毕,退出循环
注意:退出条件必须在每条边遍历完后立即检查,而不是四条边全部走完再检查。因为矩阵不一定是正方形,可能在某一条边走完后就已经遍历完了。比如一个 1×3 的矩阵 [1,2,3],遍历完顶层后 top++ 就已经 top > bottom 了,此时应该立即退出,不能再走右层、底层、左层
举例说明
以 matrix = [[1,2,3],[4,5,6],[7,8,9]] 为例
初始:left=0, top=0, right=2, bottom=2
| 步骤 | 遍历边 | 路径 | 收缩 | 边界 |
|---|---|---|---|---|
| 1 | 顶层 左→右 | 1,2,3 | top++ → top=1 | top≤bottom,继续 |
| 2 | 右层 上→下 | 6,9 | right-- → right=1 | right≥left,继续 |
| 3 | 底层 右→左 | 8,7 | bottom-- → bottom=1 | bottom≥top,继续 |
| 4 | 左层 下→上 | 4 | left++ → left=1 | left≤right,继续 |
第二轮:left=1, top=1, right=1, bottom=1
| 步骤 | 遍历边 | 路径 | 收缩 | 边界 |
|---|---|---|---|---|
| 5 | 顶层 左→右 | 5 | top++ → top=2 | top>bottom,退出! |
最终结果为 [1,2,3,6,9,8,7,4,5]
- 时间复杂度:O(mn),每个元素遍历一次
- 空间复杂度:O(1),只用了四个边界变量(结果数组不算额外空间)


