螺旋矩阵 II 边界收缩模拟法:从零生成顺时针 n×n 矩阵的完整题解(AlgoNote 0059)
教程文档知识库【免费下载链接】AlgoNote⛽️「算法通关手册」从零开始的「算法与数据结构」学习教程200 道「算法面试热门题目」1000 道「LeetCode 题目解析」持续更新中项目地址https://gitcode.com/gh_mirrors/le/AlgoNote点击查看免费下载本篇技术指南以「算法通关手册」AlgoNote 中的 0059. 螺旋矩阵 II 题解 为主体系统讲解如何用「边界收缩 模拟」的思路在 $n \times n$ 矩阵中按顺时针顺序填入 $1 \sim n^2$ 的整数。读完本文你将掌握螺旋遍历类题目的核心套路——四边界收缩法并能举一反三地解决螺旋矩阵系列的读、写、行走三类问题。题目概述题目编号LeetCode 0059力扣编号 59标签数组、矩阵、模拟难度中等题意给你一个正整数 $n$要求生成一个包含 $1 \sim n^2$ 所有元素、且元素按顺时针顺序螺旋排列的 $n \times n$ 正方形矩阵matrix。例如当 $n 3$ 时期望的输出为[[1, 2, 3], [8, 9, 4], [7, 6, 5]]数字从左上角 1 开始先向右填满第一行再向下、向左、向上像蜗牛壳一样逐圈向中心收缩直到填满 $n^2$ 个格子。本题与 54. 螺旋矩阵 构成一对互逆题目54 题是把一个给定的二维矩阵按螺旋顺序读出来而 59 题是把数字按螺旋顺序写进去。两者的访问轨迹完全相同区别仅在于 54 题用append收集元素、59 题用下标赋值填充元素理解这一点后两道题可以互相印证。解题思路边界收缩模拟法核心思想螺旋矩阵的访问轨迹有一个显著规律总是沿着当前可行区域的四条边前进走完一条边后该边所在的方向边界就要向内收缩。因此我们不需要维护复杂的转向状态机只需要维护四个边界变量即可up当前可填区域的上边界行号down当前可填区域的下边界行号left当前可填区域的左边界列号right当前可填区域的右边界列号每一轮循环按顺时针依次完成四段填充沿上边界up从左到右填充列left → right沿右边界right从上到下填充行up → down沿下边界down从右到左填充列right → left沿左边界left从下到上填充行down → up。每完成一段填充就把对应的边界向内收缩一位使未填区域不断缩小直到全部 $n^2$ 个格子被填满。边界收缩的流程细节以 $n 4$ 为例填充顺序如下第一圈(0,0)→(0,3)填 1、2、3、4(1,3)→(3,3)填 5、6、7、8(3,2)→(3,0)填 9、10、11、12(2,0)→(1,0)填 13、14、15收缩边界后第二圈只剩中间 $2 \times 2$ 的区域(1,1)→(1,2)填 16、17(2,2)填 18(2,1)填 19此时所有格子已填满。[[1, 2, 3, 4], [12, 13, 14, 5], [11, 16, 15, 6], [10, 9, 8, 7]]每次收缩后必须立刻检查边界是否发生越界交叉如up down一旦发生说明所有格子都已访问完应立即跳出循环。这正是while True循环搭配四个break判断的原因——四个方向任意一个判断触发都代表螺旋已经走到尽头。代码实现下面给出题解文档中的完整实现思路 1模拟class Solution: def generateMatrix(self, n: int) - List[List[int]]: matrix [[0 for _ in range(n)] for _ in range(n)] up, down, left, right 0, len(matrix) - 1, 0, len(matrix[0]) - 1 index 1 while True: for i in range(left, right 1): matrix[up][i] index index 1 up 1 if up down: break for i in range(up, down 1): matrix[i][right] index index 1 right - 1 if right left: break for i in range(right, left - 1, -1): matrix[down][i] index index 1 down - 1 if down up: break for i in range(down, up - 1, -1): matrix[i][left] index index 1 left 1 if left right: break return matrix代码关键点逐行拆解初始化二维矩阵matrix [[0 for _ in range(n)] for _ in range(n)]创建 $n \times n$ 的全零矩阵。这里用列表推导式按行逐层创建避免直接使用[[0] * n] * n造成各子列表共享同一引用的问题后者的修改会同时影响所有行。边界初始化up 0、down n - 1、left 0、right n - 1与矩阵的行列下标范围严格对应。注意len(matrix[0])与n相等此处用矩阵自身维度推导边界代码更具通用性。计数器index从 1 递增到 $n^2$充当当前应填入的数字。每次填充一个格子后自增。四段 for 循环分别用range(left, right 1)、range(up, down 1)、range(right, left - 1, -1)、range(down, up - 1, -1)精确覆盖四条边上的格子。第三、四段使用步长为 -1 的逆序 range这是实现从右到左、从下到上的关键写法。收缩与判停每段填充后立即收缩对应边界并检查交叉条件up down、right left、down up、left right。由于正方形矩阵的对称性四个判断中任意一个触发即代表螺旋结束直接break退出。复杂度分析时间复杂度$O(n^2)$。矩阵共有 $n^2$ 个格子每个格子恰好被赋值一次四段循环的迭代次数之和严格等于 $n^2$。空间复杂度$O(n^2)$。除了返回的答案矩阵本身占用的空间外只使用了常数个边界变量和计数器因此额外空间复杂度为 $O(1)$。从实现层面看所有操作都是对二维数组的直接下标读写不涉及元素搬移或额外数据结构符合 01_01 数组基础 中数组支持随机访问、按下标定位元素为 $O(1)$的特性——这正是模拟法高效的原因$n^2$ 次 $O(1)$ 的赋值操作叠加即为 $O(n^2)$ 的总复杂度。运行验证与输出示例用本仓库题解文档中的代码在 Python 3 环境下实际运行得到如下输出与题目要求完全一致n 1 - [[1]] n 2 - [[1, 2], [4, 3]] n 3 - [[1, 2, 3], [8, 9, 4], [7, 6, 5]] n 4 - [[1, 2, 3, 4], [12, 13, 14, 5], [11, 16, 15, 6], [10, 9, 8, 7]] n 5 - [[1, 2, 3, 4, 5], [16, 17, 18, 19, 6], [15, 24, 25, 20, 7], [14, 23, 22, 21, 8], [13, 12, 11, 10, 9]]几个可以直接肉眼校验的特征$n 1$ 时矩阵退化为单元素[[1]]模拟法第一段循环填充后up down立即触发跳出返回正确结果无需特判每条边上数字都是连续递增的且数字 1 永远位于左上角 $(0, 0)$$n^2$ 一定落在矩阵中央奇数 $n$ 时严格居中这是因为螺旋逐圈收缩的特性决定了最后一步到达中心。边界情况与易错点n 1的特例第一段循环填完matrix[0][0] 1后up变为 1up down1 0成立立即退出。整个流程天然正确无需单独处理。逆序 range 的边界第三、四段循环写range(right, left - 1, -1)而非range(right, left, -1)因为 Python 的range(start, stop, step)是左闭右开区间必须把 stop 设为left - 1才能覆盖到下标left本身。收缩顺序与判断时机先收缩、再判断才能准确反映这条边已经走完。若把判断放在收缩之前会导致边界状态滞后一轮产生越界赋值或死循环。不要使用[[0] * n] * n初始化Python 中*复制的是外层列表的引用[[0] * n] * n会让所有行共享同一个内层列表修改任一元素会传染整列必须用列表推导式逐行创建。延伸螺旋矩阵系列的同源变体边界收缩模拟法是螺旋类题目的通用武器本仓库中还收录了该系列的其他变体可与本题互相印证54. 螺旋矩阵给定 $m \times n$ 矩阵按顺时针读出全部元素。代码框架与 59 题几乎一致区别仅在于用ans.append(matrix[up][i])收集元素而非赋值且读完即返回、不需维护计数器。建议两题对照学习体会读与写的对称性。LCR 146. 螺旋遍历二维数组同属按顺时针输出矩阵元素的题目其实现额外处理了m 0或n 0的空矩阵边界可作为矩阵可能为空的健壮性参考。885. 螺旋矩阵 III从任意起点出发、允许走出网格边界的螺旋行走问题。它改用方向数组 步长递增的思路东、南、西、北四个方向每个方向走的步数为 1、1、2、2、3、3…与本题的四边界收缩形成螺旋问题的两种典型解法范式。这三道题在 00_06 分类题目列表 中均被归入数组、矩阵、模拟分类属于面试中高频出现的模拟类基础题型。总结螺旋矩阵 II 的核心考点是对二维数组边界的精细控制与模拟循环的跳出条件设计。通过维护up / down / left / right四个边界变量、按顺时针逐边填充并收缩、在边界交叉时及时跳出即可用 $O(n^2)$ 的时间复杂度、$O(1)$ 的额外空间完成整个矩阵的生成。掌握本题后建议继续研读仓库中的 54. 螺旋矩阵读方向与 885. 螺旋矩阵 III行走方向两道姊妹题将边界收缩与方向步长两种范式都练熟螺旋类题目便可一网打尽。赞分享教程文档知识库【免费下载链接】AlgoNote⛽️「算法通关手册」从零开始的「算法与数据结构」学习教程200 道「算法面试热门题目」1000 道「LeetCode 题目解析」持续更新中项目地址https://gitcode.com/gh_mirrors/le/AlgoNote点击查看免费下载相关推荐algorithm-base 图解 LeetCode 59 螺旋矩阵 II从读取到写入的边界收缩法生成 n 阶螺旋方阵algorithm base 图解 LeetCode 59 螺旋矩阵 II从读取到写入的边界收缩法生成 n 阶螺旋方阵 导读 本文讲解 LeetCode 59文档教程知识库LeetCode-Book 螺旋矩阵题解四边界收缩法模拟顺时针遍历54. Spiral MatrixLeetCode Book 螺旋矩阵题解四边界收缩法模拟顺时针遍历54. Spiral Matrix 导读 本文以 LeetCode Book 仓库中《K示例工程螺旋矩阵 II 四边界收缩解法详解以 LeetCode-Book 的 lc_59 实现为例螺旋矩阵 II 四边界收缩解法详解以 LeetCode Book 的 lc_59 实现为例 本篇技术指南以 selected_coding_interview示例工程上一篇Magenta.js安全考量与实践保护你的AI模型与用户数据下一篇如何用Open Mercato自定义字段扩展CRM数据Custom Fields实战教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考