题目描述
思路解析
一句话答案:LeetCode 885 螺旋矩阵 III:按东南西北方向转圈、螺旋步长每两段加一步来模拟行走,走到界外照走、只把界内格子记进答案,数满 rows×cols 个就停,时间 O(max(rows,cols)²)。
从一个起点螺旋着走,要收集出什么
给一个 rows 行、cols 列的网格,从 (rStart, cStart) 出发、面朝东,按顺时针向外螺旋,把走到的格子按顺序收进答案。走到网格外也照走、稍后绕回来,直到 rows×cols 个格子收齐,返回坐标列表。题面例子 rows=2、cols=2、起点 (0,0),答案 [[0,0],[0,1],[1,1],[1,0]]。
圈数不固定,拿什么判断走完了
起点不保证在角落,螺旋要绕几圈才能盖住整张网格,事先算不出来。开个 rows×cols 的二维数组标记走过的格子、再靠绕够圈数收尾是个直觉,可圈数根本不固定,起点越偏空绕的圈越多,固定圈数当终点不是早停漏格就是多绕。开 visited 数组标记也白费:螺旋不会重复踩同一个界内格,白花一份 O(rows×cols) 空间。
两根尺子:方向转圈,步长每两段加一
管用的是两根尺子。方向永远按东→南→西→北顺时针循环,落到行列上就是右、下、左、上。第二根是螺旋步长,即每换两段方向就多走一步:东走 1、南走 1,再西走 2、北走 2,接着东走 3、南走 3,凑成 1,1,2,2,3,3。每两段才加,是因为螺旋每绕半圈横边竖边各长一格,两段共用一个步长正好撑大这半圈。还有一条规矩:每迈一格先看在不在网格里,在就记、不在照走不记。
起点先入队,四段一组循环着往外铺
落到代码上,先把起点放进答案;只有 1 格就直接返回。开一个永真循环,用 k 记步长、从 1 起,每轮结束 k 加 2。每轮走四段:东 k 步、南 k 步、西 k+1 步、北 k+1 步,让相邻两轮拼出 1,1,2,2,3,3 的递增。每走一格判断行、列是否都落在 [0,rows) 和 [0,cols) 里,是就把坐标追进答案,并看已记数够不够 rows×cols,够了就立刻返回;界外格子不记,指针照旧往前挪。
rows=2、cols=2、起点 (0,0) 跟到底
先把起点 (0,0) 记成第 1 个。步长 k 先取 1:向东走 1 步到 (0,1),行 0、列 1 都在界内,记成第 2 个;向南走 1 步到 (1,1),仍在界内,第 3 个;再向西走第一步到 (1,0),还在界内,第 4 个——已记 4 个恰好等于 2×2,立刻返回。答案 [[0,0],[0,1],[1,1],[1,0]],正是题面坐标。这张小网格四步全在界内、没演到界外空走;换个贴边起点或窄长的网格,南边西边那几步就会掉出网格,照走不记才上场。
界外空走的步数,和最长边的平方同阶
最坏起点落在角落,螺旋要绕很大圈才够得着远端,连界外空走一起算,总步数和最长边的平方同阶,即 O(max(rows,cols)²);100×100 网格也就一万多步。空间只有几个指针变量,不算必须输出的答案列表就是 O(1)。
界外那步最忌停下或跳过不走:螺旋会少绕一格、整条路径错位,界外必须照走、只是不记。步长也别四段都用同一个 k,否则节奏成 1,1,1,1、凑不出扩张的螺旋,得前两段 k、后两段 k+1,k 每轮加 2。收尾也别靠绕几圈来判,起点不同、圈数就不同,只有已记数等于总格数才靠得住。
▶ 动画逐步走查(文字版)——想跟着上方动画一帧帧对照就展开
记住两根尺子:方向东南西北转圈,步长每两段加一。下面用一张小网格把这两根尺子走一遍。
网格总览 · 起点 (1,1):看这张图。真正的网格是上面绿框这两行,共 2 行 4 列。最下面一条灰带代表「网格外面」,等会儿螺旋会踩进去。绿色的 (1,1) 是起点,先把它记成答案里的第 1 个。
步长规律 · 1,1,2,2,3,3:先把步长规律记牢。出发先向东走 1 步,再向南走 1 步;然后向西走 2 步,向北走 2 步;接着向东走 3 步,向南走 3 步。就是每两段用同一个步长,走完两段步长就加一。
向东走 · 落到 (1,2):出发了。第一段向东走 1 步,指针落到 (1,2)(橙色)。每走到一格,先问一句:这格在网格里吗?
在界内 · 记成第 2 个:(1,2) 的行和列都没越界,在网格里。把它涂绿、记成答案的第 2 个,右边 ans 队伍多了一个坐标。
向南走 · 落到 (2,2):指针沿着南方向迈一步,落到 (2,2)。还是老规矩,先判断它在不在真实网格里。
在界外 · 照走但不记:(2,2) 掉到灰带里,也就是网格外面。这一步照样要走,但不能记进答案,所以打个红叉跳过。注意:虽然没记,人还是站在这里继续往前走。
向西走 · 落到 (2,1):指针沿着西方向迈一步,落到 (2,1)。还是老规矩,先判断它在不在真实网格里。
在界外 · 照走但不记:(2,1) 又是界外,继续打叉跳过,ans 不变,但脚步不停,接着按规律往下走。
向西走 · 落到 (2,0):指针沿着西方向迈一步,落到 (2,0)。还是老规矩,先判断它在不在真实网格里。
在界外 · 照走但不记:(2,0) 又是界外,继续打叉跳过,ans 不变,但脚步不停,接着按规律往下走。
向北走 · 落到 (1,0):指针沿着北方向迈一步,落到 (1,0)。还是老规矩,先判断它在不在真实网格里。
在界内 · 记成第 3 个:(1,0) 的行和列都没越界,在网格里。把它涂绿、记成答案的第 3 个,右边 ans 队伍多了一个坐标。
向北走 · 落到 (0,0):指针沿着北方向迈一步,落到 (0,0)。还是老规矩,先判断它在不在真实网格里。
在界内 · 记成第 4 个:(0,0) 同样在界内,收进答案,成为第 4 个。
向东走 · 落到 (0,1):指针沿着东方向迈一步,落到 (0,1)。还是老规矩,先判断它在不在真实网格里。
在界内 · 记成第 5 个:(0,1) 同样在界内,收进答案,成为第 5 个。
向东走 · 落到 (0,2):指针沿着东方向迈一步,落到 (0,2)。还是老规矩,先判断它在不在真实网格里。
在界内 · 记成第 6 个:(0,2) 同样在界内,收进答案,成为第 6 个。
向东走 · 落到 (0,3):指针沿着东方向迈一步,落到 (0,3)。还是老规矩,先判断它在不在真实网格里。
在界内 · 记成第 7 个:(0,3) 同样在界内,收进答案,成为第 7 个。
向南走 · 落到 (1,3):指针沿着南方向迈一步,落到 (1,3)。还是老规矩,先判断它在不在真实网格里。
在界内 · 记成第 8 个:(1,3) 同样在界内,收进答案,成为第 8 个。
收集完毕 · 共 8 个格子:当记录数等于网格总格数 8,就说明全走遍了,立刻收工。右边 ans 这一长串坐标,正是按螺旋访问顺序排好的最终答案。中间踩进灰带的那几步,一个都没混进来。
边界先想清:单格直接返回、单行只有东向有效、起点贴边时头几步常落界外。
两个高频追问:计数器代替 visited 数组省空间;界外空走是平方级、规模内完全可接受。
参考代码
from __future__ import annotationsfrom typing import *from collections import *from functools import *from itertools import *from math import *from heapq import *from bisect import *class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = rightclass ListNode: def __init__(self, val=0, next=None): self.val = val self.next = nextclass Solution: def spiralMatrixIII( self, rows: int, cols: int, rStart: int, cStart: int ) -> List[List[int]]: ans = [[rStart, cStart]] if rows * cols == 1: return ans k = 1 while True: for dr, dc, dk in [[0, 1, k], [1, 0, k], [0, -1, k + 1], [-1, 0, k + 1]]: for _ in range(dk): rStart += dr cStart += dc if 0 <= rStart < rows and 0 <= cStart < cols: ans.append([rStart, cStart]) if len(ans) == rows * cols: return ans k += 2复杂度
- 时间:O(max(rows, cols)²),螺旋边长一圈圈变大,含界外空走的步数与最长边的平方同阶
- 空间:O(rows · cols),只有答案列表本身的开销,不算它则是 O(1) 的额外变量
易错点
面试追问把动画讲成自己的话
追问为什么不开一个二维 visited 数组来标记走过的格子?
追问界外空走会不会让时间复杂度爆掉?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
可能的二分法
LeetCode 886 · 中等 · 沿着 图论套路 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题