题目描述
思路解析动画文字版
起点 · 一张空棋盘:这是 3×3 的空盘子(「·」表示还没填)。我们要把 1 到 9 按顺时针螺旋一格一格填进去,填完计数到 9 就结束。
核心思路 · 四条边界:不去记「现在朝哪个方向、要不要拐弯」那么乱,而是用四条边界 top/bottom/left/right 圈出「还没填的矩形」。每填完一条边,就把对应的边界往里收一格,矩形越缩越小。
一圈分四步:每绕一圈就是这固定四步:走完上边 top 下移、走完右边 right 左移、走完下边 bottom 上移、走完左边 left 右移。然后用「top≤bottom 且 left≤right」判断里面还有没有格子要填。
初始边界:开局四条边界框住整张表:top=0、bottom=2、left=0、right=2,要填的数字 num 从 1 开始。笔尖(紫色)停在左上角 (0,0),准备沿上边向右走。
上边 → · 填 (0,0)=1:沿着上边 top=0 这一行,从 left 到 right 走。第一格 (0,0) 填 1,num 加到 2。
上边 → · 填 (0,1)=2:继续向右,(0,1) 填 2。前一格 (0,0) 变蓝表示已填定,笔尖移到 (0,1)。
上边 → · 填 (0,2)=3:走到最右 (0,2) 填 3,上边到头了。上边这一行已经填满 1、2、3。
上边收缩 · top 下移:上边填完,把 top 从 0 收到 1——第 0 行以后不用再碰。接着拐弯沿右边 right=2 这一列向下走,笔尖移到 (1,2)。
右边 ↓ · 填 (1,2)=4:拐弯向下,沿右边 right=2 这一列从 top 到 bottom 走。(1,2) 填 4,num 加到 5。
右边 ↓ · 填 (2,2)=5:继续向下到底,(2,2) 填 5,右边到底了。整张表的右边一列 3、4、5 连成了。
右边收缩 · right 左移:右边填完,把 right 从 2 收到 1。再拐弯沿下边 bottom=2 这一行向左走,笔尖移到 (2,1)。
下边 ← · 填 (2,1)=6:拐弯向左,沿下边 bottom=2 这一行从 right 到 left 走。(2,1) 填 6,num 加到 7。注意方向反过来了,从右往左。
下边 ← · 填 (2,0)=7:继续向左到头,(2,0) 填 7,下边走完。最下面一行此刻是 7、6、5(从左看),正是螺旋绕回来的样子。
下边收缩 · bottom 上移:下边填完,把 bottom 从 2 收到 1。最后拐弯沿左边 left=0 这一列向上走,笔尖移到 (1,0)。
左边 ↑ · 填 (1,0)=8:拐弯向上,沿左边 left=0 这一列从 bottom 到 top 走。(1,0) 填 8,num 加到 9。外面这一圈 1..8 已经绕满了。
左边收缩 · left 右移:左边填完,把 left 从 0 收到 1。现在四条边界全收成 top=bottom=1、left=right=1——框住的只剩正中央 (1,1) 一格了,笔尖移过去。
最里圈 · 填中心 (1,1)=9:新一圈又从「沿 top 行向右」开始:(1,1) 填 9,num 到 10。这就是最中心那一格,1..9 全填满了。
守护判断 · 中心不再重填:填完中心后 top 收到 2。此时若没有那两个 if 守护,下边、左边的循环又会去碰中心格 (1,1)(红色)造成重填。正因为 top≤bottom 不成立,守护把它们挡住了,中心只被填一次。
完成 · 螺旋成型:填完中心后 top 又收到 2,已经大于 bottom=1,「top≤bottom」不成立,循环退出。最终结果 [[1,2,3],[8,9,4],[7,6,5]]——一个漂亮的顺时针螺旋。
回看 · 外圈那一环:回看一眼螺旋的层次:紫色高亮的 1→2→3→4→5→6→7→8 是最外一圈,沿着边界顺时针绕了一整圈。
回看 · 收到最里的中心:外圈绕完,四条边界一起往里收,剩下的最里一层就是中心 9。n 更大时会一圈圈往里收很多层,规律完全一样:右→下→左→上,每走完一边收一条边界。
一个关键细节:当 n 是奇数、收到最后只剩一行或一列时,上边和右边已经把它填了。如果不加判断又去走下边、左边,就会重复填或越界。所以走下边、左边前各补一个 if 守护。
本质金句:螺旋遍历类题的统一套路:用四条边界圈住「还没处理的矩形」,按右→下→左→上固定顺序走,每走完一条边就把那条边界往里收,矩形缩到空为止。读、填都一样。
易错实演 · 漏判 if 重复填:假设收到最后只剩中心一格 (1,1)(红色):上边那一步已经把它填成 9。若走下边、左边时不加 if 判断,会再去写这一格,导致数字被覆盖错乱——这正是要加守护的原因。
边界三连:n=1 单格、n=2 无中心、n 奇数有正中格,这三类都靠同一套四边界模板兜住。关键就是那两个 if 守护,让奇数中心不被重复填。
面试追问:面试常把 I 和 II 一起问,强调「读 vs 写、框架同源」;再追问别的写法时,能说出方向数组转向法会加分。
参考代码
class Solution: def generateMatrix(self, n): m = [[0] * n for _ in range(n)] top, bottom, left, right = 0, n - 1, 0, n - 1 num = 1 while top <= bottom and left <= right: for j in range(left, right + 1): m[top][j] = num; num += 1 top += 1 for i in range(top, bottom + 1): m[i][right] = num; num += 1 right -= 1 if top <= bottom: for j in range(right, left - 1, -1): m[bottom][j] = num; num += 1 bottom -= 1 if left <= right: for i in range(bottom, top - 1, -1): m[i][left] = num; num += 1 left += 1 return m复杂度
- 时间:O(n²),每个格子恰好被填一次,总共 n² 个格子
- 空间:O(1),除返回的矩阵外,只用了几个边界变量,额外空间常数
易错点
面试追问把动画讲成自己的话
追问和「螺旋矩阵 I」(给矩阵按螺旋读出)有什么区别?
追问除了四边界,还有别的写法吗?
追问如果要按逆时针螺旋填呢?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
矩阵置零
LeetCode 73 · 中等 · 沿着 矩阵套路 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题