跳到正文
第 54 题中等

螺旋矩阵

Spiral Matrix

按顺时针螺旋的顺序,从外到内把 m × n 矩阵里的所有元素依次取出来。

在力扣中练习

题目描述

给你一个 m 行 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]

 

提示:

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 10
  • -100 <= matrix[i][j] <= 100

解题思路

主解法

四条边界 · 逐层收缩

上下左右各走一条边,走完就缩一格

按“向右、向下、向左、向上”一格格模拟需要记录方向和访问状态。也可以维护尚未读取区域的四条边界,每次读完一条边就把它从矩形里去掉。

自拟矩阵 [[5,8,2,9,4],[7,1,6,3,0],[12,11,10,14,13]] 是 3×5 的长方形,值不按访问顺序排列,因此要真正跟随位置读取。

分步图解

四条边界围住尚未访问的矩形,按上、右、下、左收缩。

矩阵 · 小字为访问次序
5
8
2
9
4
7
1
6
3
0
12
11
10
14
13
res
[ ]
1 / 5
每读完一边就缩掉它,下一条边使用更新后的范围。

读上边后 top 加一,右边后 right 减一,底边后 bottom 减一,左边后 left 加一。后续边都要使用最新范围,四个角才不会重复。

图解
矩阵 · 小字为访问次序
51
82
23
94
45
712
113
614
315
06
1211
1110
109
148
137
res
58294013141011127163
普通节点已确认 / 结果
内圈只剩一行,底边判断失败,因此不会重复读取。

外圈完成后内部只剩 [1,6,3] 一行,读完上边就已经读完它。底边必须重新判断 top<=bottom;同理左边也要检查 left<=right。最终每个位置只追加一次,而不是按值去重。

时间 O(m·n)空间 O(1)(不计输出)

易错点

  • 右边那一列从 0 开始遍历而不是从 top 开始,右上角那一格会被收两次。
  • 底边、左边不加 if:只剩一行(或一列)时会把同一行倒着再收一遍。
  • while 条件两个都要写:只留一个时,单行或单列矩阵会多走一轮,甚至把元素重复收集。
对照解法

方向数组 · 撞墙右转

站在格子上往前走,走不动就右转 90°

正确的方向模拟,需要访问标记;主解法用四条边界省掉这部分辅助空间。

另一种写法更像「模拟走路」:站在 (r, c) 上,朝当前方向走一步;如果下一步越界,或者踩到已经访问过的格子,就右转 90° 再走。

用一个 seen 数组记录走过哪些格子,循环 m * n 次正好把所有格子走完。

好处是不用维护四条边,思路和题目描述一字不差;代价是多开一个 O(m·n) 的 visited 数组。方向数组按「右、下、左、上」排列,右转就是 (d + 1) % 4。

写的时候注意:判定「下一步不能走」之后,要用转向后的方向重新算一次 nr, nc,否则还停留在原来的方向上,会在原地打转。

  1. 1初始位置 (0,0),方向朝右,seen 全部为 false。
  2. 2收集当前格并标记 seen。
  3. 3算下一步:越界或已访问就 d = (d + 1) % 4,再重算下一步。
  4. 4移动过去,重复 m * n 次。
时间 O(m·n)空间 O(m·n)

易错点

  • 转向后忘记重算 nr、nc,下一步还是原来的方向,死循环。
  • seen 标记写在 push 之后才做,容易在转角处把同一格重复加入结果。

代码与演示

主解法配有图解;对照解法用于比较思路、复杂度或实现方式。

演示输入matrix = [[5,8,2,9,4],[7,1,6,3,0],[12,11,10,14,13]]

四条边界围住尚未访问的矩形,按上、右、下、左收缩。

矩阵 · 小字为访问次序
5
8
2
9
4
7
1
6
3
0
12
11
10
14
13
res
[ ]
1 / 10
查看 C++ 代码

延伸阅读

  • 螺旋矩阵 II(59)是反过来的:按螺旋顺序往 n × n 矩阵里填 1 到 n²。
  • 「逐层处理」的边界写法在旋转图像(48)里也用得上,只是那一题动手的是四条边上的元素交换。
  • 之字形遍历(103、498)不要硬套四条边,方向数组 + 转向判断更省事。