蛇形矩阵算法解析:从边界控制到代码实现

发布时间:2026/10/18 7:37:50
蛇形矩阵算法解析:从边界控制到代码实现 1. 蛇形矩阵到底在考什么蛇形矩阵这个题在编程练习平台里算是很经典的一道二维数组模拟题。我第一次碰到它的时候觉得不就是把数字按顺序填进去嘛能有多难。结果真上手写的时候边界条件把我折腾得够呛。后来刷的题多了回头再看这道题才发现它表面上考的是数组操作实际上考的是你对边界控制和方向切换的理解。先把题目说清楚。蛇形矩阵通常指的是这样一个东西给定一个正整数 n生成一个 n 行 n 列的方阵数字从 1 开始按照蛇形走位依次填入。所谓蛇形走位就是第一行从左到右填到了行尾之后往下走一格第二行从右到左填到了行首再往下走一格第三行又从左到右如此反复直到填满整个矩阵。举个例子n4 的时候结果是这样的1 2 3 4 8 7 6 5 9 10 11 12 16 15 14 13看起来很简单对吧但如果你真的动手写过就会知道这里面有几个很容易翻车的地方。比如行末和行首的转向判断、奇偶行的处理差异、循环终止条件的设置每一个细节没处理好输出就会乱掉。这道题适合什么人看我觉得两类人最需要认真琢磨。一类是刚学完数组和循环、想找个题练手的初学者蛇形矩阵能帮你把二维数组的索引操作练得很扎实。另一类是准备面试的人这类模拟题在笔试环节出现频率不低它不考你什么高级算法就考你能不能把逻辑理清楚、把代码写对这恰恰是面试官想看的底层能力。接下来我会从最直观的解法讲起然后逐步分析几种不同的实现思路把每一步为什么这么做都掰开揉碎说清楚。中间还会穿插我自己踩过的坑和调试技巧争取让你看完就能自己写出来而且能举一反三。2. 从手动填数到代码实现的思维转换2.1 用最笨的办法先理解规律在写代码之前我建议你先拿张纸手动把 n5 的蛇形矩阵画出来。别觉得这是浪费时间我见过太多人上来就敲代码结果写到一半发现规律没搞明白又回头重新推。n5 的蛇形矩阵长这样1 2 3 4 5 10 9 8 7 6 11 12 13 14 15 20 19 18 17 16 21 22 23 24 25你手动填一遍就会发现几个规律。第一数字是连续递增的从 1 到 n²一个不多一个不少。第二每一行的方向是交替的奇数行第1、3、5行从左往右偶数行第2、4行从右往左。第三行与行之间的衔接点很关键——第一行填到最右边之后下一个数字在第二行的最右边第二行填到最左边之后下一个数字在第三行的最左边。这三个规律看起来是废话但它们直接决定了你代码的结构。很多人写的时候只盯着“怎么填数字”忽略了“什么时候换行、换行之后从哪边开始”这个核心问题。2.2 方向切换的本质是什么我们把问题抽象一下。你有一个 n×n 的二维数组有一个当前数字 num 从 1 开始有一个当前位置 (i, j)。每一步你要做的是把 num 填到 (i, j)然后 num 加一然后决定下一步往哪走。在蛇形矩阵里方向只有两种向右或者向左。但什么时候切换方向答案是当你走到当前行的尽头时。这里就引出一个关键判断什么叫“走到尽头”对于从左往右的行尽头是 j n-1对于从右往左的行尽头是 j 0。一旦到达尽头你就需要换到下一行同时把方向反过来。用伪代码表示就是i 0, j 0, num 1 direction right while num n * n: matrix[i][j] num num 1 if direction right: if j n - 1: i 1 direction left else: j 1 else: if j 0: i 1 direction right else: j - 1这段伪代码的逻辑非常清晰但它有一个隐藏的问题当 i 增加到 n 的时候循环其实已经该结束了但因为 num 的条件控制不会越界访问。不过如果你在换行的时候没有做好判断就可能在最后一行之后还试图访问 matrix[n][...]导致数组越界。2.3 为什么我不推荐用方向数组有些教程会教你用方向数组来做类似这样directions [(0, 1), (0, -1)] # 右、左然后用一个索引来控制当前方向。这种做法在更复杂的矩阵题比如螺旋矩阵里确实好用但对于蛇形矩阵来说我觉得有点杀鸡用牛刀。蛇形矩阵只有两个方向而且切换规则非常固定直接用 if-else 判断反而更直观、更不容易出错。当然如果你是在练习阶段想刻意训练自己用方向数组的思维那也无可厚非。但如果是面试场景代码的可读性很重要面试官更想看到你清晰地表达逻辑而不是炫技。3. 三种实现方案的对比与选择3.1 逐行填充法最直观的写法逐行填充法的思路是外层循环遍历每一行内层循环遍历该行的每一列根据行号的奇偶性决定填充方向。def snake_matrix(n): matrix [[0] * n for _ in range(n)] num 1 for i in range(n): if i % 2 0: # 偶数行从左到右 for j in range(n): matrix[i][j] num num 1 else: # 奇数行从右到左 for j in range(n - 1, -1, -1): matrix[i][j] num num 1 return matrix这段代码短小精悍逻辑一目了然。它的时间复杂度是 O(n²)因为要填充 n² 个位置空间复杂度也是 O(n²)因为要存储整个矩阵。对于这道题来说这已经是最优的复杂度了因为输出本身就需要 n² 个元素。我特别喜欢这种写法的原因是它把“行”和“列”的关系处理得很干净。你不需要维护额外的方向变量也不需要担心边界切换的问题行号的奇偶性天然就决定了方向。但这种方法有一个局限它只适用于规则的行交替蛇形矩阵。如果题目变成“之字形遍历”或者“对角线蛇形”这种写法就不适用了你得回到更通用的模拟思路。3.2 模拟行走法更通用的思路模拟行走法就是我前面伪代码描述的那种方式维护当前位置和当前方向一步一步地走走到边界就转向。def snake_matrix_simulate(n): matrix [[0] * n for _ in range(n)] i, j, num 0, 0, 1 direction 1 # 1 表示向右-1 表示向左 while num n * n: matrix[i][j] num num 1 if direction 1: if j n - 1: i 1 direction -1 else: j 1 else: if j 0: i 1 direction 1 else: j - 1 return matrix这种写法的好处是通用性强。如果你把方向切换的条件改一改就能变成螺旋矩阵、对角线遍历等其他变体。缺点是代码稍微长一点而且需要小心处理 i 和 j 的越界问题。我在实际写的时候习惯在 while 循环里加一个判断如果 i n直接 break。虽然理论上 num 的条件会先触发但多加一层保险总没错。特别是在面试的时候面试官很可能会问你“如果 n0 或者 n负数怎么办”这时候你就需要提前处理这些边界情况。3.3 数学公式法看起来高级但没必要还有一种思路是找数学公式。蛇形矩阵中每个位置 (i, j) 的值其实可以用公式直接算出来不需要模拟填充。对于偶数行 i0-indexedmatrix[i][j] i * n j 1。 对于奇数行 imatrix[i][j] i * n (n - j)。def snake_matrix_formula(n): matrix [] for i in range(n): if i % 2 0: row [i * n j 1 for j in range(n)] else: row [i * n (n - j) for j in range(n)] matrix.append(row) return matrix这种写法确实很优雅一行代码就能生成一行数据。但说实话在实际面试中我不太推荐主动写这种解法。原因有两个第一它需要你推导公式推导过程容易出错第二面试官可能觉得你在背题而不是在展示解题思维。当然如果你能清晰地解释公式的推导过程那用公式法反而能体现你的数学功底。关键是要能说清楚“为什么奇数行的公式是这样的”而不是直接甩出一个公式。3.4 三种方案的对比方案代码长度可读性通用性推荐场景逐行填充法短高低面试快速手写模拟行走法中中高需要扩展到其他变体数学公式法最短中低追求代码简洁我的建议是面试的时候优先写逐行填充法因为它最不容易出错而且面试官一眼就能看懂你的逻辑。如果面试官追问“能不能用其他方法”你再展示模拟行走法说明你理解更通用的解题思路。4. 那些年我踩过的边界坑4.1 行末转向时忘记换行这是我第一次写蛇形矩阵时犯的错。当时我的代码是这样的if direction 1: if j n - 1: direction -1 # 只切换了方向忘记 i 1 else: j 1结果就是数字一直在第一行来回填把前面的数字覆盖掉了。调试的时候打印出来一看第一行变成了 [5, 4, 3, 2, 1]后面的行全是 0。这个错误的根本原因是我把“转向”和“换行”当成了两件事但实际上在蛇形矩阵里转向和换行是同时发生的。你走到行末的那一刻既要改变方向也要进入下一行。提示每次写边界判断的时候问自己一句“这一步之后下一个数字应该填在哪里”如果答案不明确说明你的逻辑有漏洞。4.2 奇数行和偶数行的终止条件搞反第二个坑是奇数行从右往左填的时候终止条件应该是 j 0而不是 j 0。我一开始写成了for j in range(n - 1, 0, -1): # 错误漏掉了 j0这样会导致每一奇数行的第一个位置最左边没有被填充输出结果里会出现 0。正确的写法是range(n - 1, -1, -1)注意最后一个参数是 -1表示步长为负这样才能遍历到 0。这个坑看起来很低级但在手写代码的时候特别容易犯。因为 Python 的 range 函数是左闭右开的range(n-1, -1, -1) 生成的是 n-1, n-2, ..., 1, 0刚好覆盖所有列。如果你写成 range(n-1, 0, -1)生成的是 n-1, ..., 1少了 0。4.3 n1 的特殊情况当 n1 的时候蛇形矩阵就是 [[1]]。这个情况本身不复杂但如果你在代码里做了“奇数行从右往左”的处理而 n1 时只有一行第0行偶数行那其实不会触发奇数行逻辑。但如果你用模拟行走法就要注意 while 循环的条件。我见过有人在模拟行走法里这样写while i n and j n:这个条件在 n1 的时候第一轮 i0, j0 满足条件填入 1 之后j 变成 1因为 direction1 且 j ! n-1 不成立实际上 jn-10所以会触发 i1, direction-1然后 i 变成 1循环条件 i n 不满足退出。结果是正确的。但如果你的条件写成while i n and j n and num n*n那也没问题。关键是不要写成while i n and j n那样会多走一轮导致数组越界。4.4 输出格式的坑有些题目要求输出的时候每个数字占固定宽度比如用%3d或者{:3d}格式化。如果你直接 print 列表输出会带方括号和逗号不符合题目要求。我一般会这样处理输出for row in matrix: print( .join(f{x:3d} for x in row))这样每个数字占3个字符宽度右对齐列与列之间用空格分隔看起来整齐美观。如果 n 比较大比如 n10数字可能超过3位那就需要动态计算宽度比如用len(str(n*n))来确定。5. 从蛇形矩阵延伸出去的思考5.1 螺旋矩阵和蛇形矩阵的关系蛇形矩阵是“行交替方向”螺旋矩阵是“沿着外圈顺时针或逆时针走”。两者都属于矩阵模拟题但螺旋矩阵的边界控制更复杂需要维护上下左右四个边界。如果你能把蛇形矩阵写熟练再去写螺旋矩阵会轻松很多。因为螺旋矩阵的核心也是“走到边界就转向”只不过它有四个方向而不是两个。我建议的练习顺序是先写蛇形矩阵再写对角线遍历最后写螺旋矩阵。这三个题覆盖了矩阵模拟的主要模式写完你对二维数组的掌控力会有一个明显的提升。5.2 蛇形矩阵的变体之字形遍历之字形遍历Zigzag Traversal是蛇形矩阵的升级版。它不再是整行整行地填而是沿着对角线走。比如对于矩阵1 2 3 4 5 6 7 8 9之字形遍历的输出是1, 2, 4, 7, 5, 3, 6, 8, 9。这种题目的边界控制更复杂因为你要判断什么时候往上走、什么时候往下走、什么时候换对角线。但核心思路还是一样的维护当前位置和方向走到边界就调整。5.3 实际工程中哪里会用到这些你可能会问蛇形矩阵这种题在实际工作中有用吗说实话直接用到的地方不多。但它的训练价值在于让你习惯处理二维数组的索引和边界。在图像处理、游戏开发、数据分析等领域二维数组的遍历是家常便饭。比如图像旋转、卷积操作、矩阵运算都需要你对索引有精准的控制。蛇形矩阵这种题就是帮你把这种控制力练到肌肉记忆里。另外这类题在面试中的出现频率确实不低。我统计过一些公司的笔试题目矩阵模拟题的出现概率大概在15%左右其中蛇形矩阵和螺旋矩阵是最常见的两种。所以花时间把这类题吃透投入产出比是很高的。6. 调试蛇形矩阵的实用技巧6.1 用小规模数据验证我调试这类题的时候从来不会一上来就用 n10 去测。我会先用 n1、n2、n3 这种小规模数据跑一遍确认基本逻辑没问题再逐步增大 n。n1 的输出应该是 [[1]]。 n2 的输出应该是 [[1, 2], [4, 3]]。 n3 的输出应该是 [[1, 2, 3], [6, 5, 4], [7, 8, 9]]。如果这三个都对了那基本逻辑就没问题。如果 n3 错了你就很容易定位到是哪一行的逻辑出了问题。6.2 打印中间状态在模拟行走法里我习惯在每次填充之后打印当前的位置和方向print(f填入 {num-1} 到 ({i}, {j}), 方向{direction})这样你能清楚地看到每一步的走向一旦发现方向切换的时机不对马上就能定位到是哪一行代码的问题。6.3 用断言做自检如果你是在本地写代码可以加一些断言来验证结果的正确性flat [x for row in matrix for x in row] assert sorted(flat) list(range(1, n*n1)), 数字不连续或有重复这个断言能帮你快速发现“数字覆盖”或“数字遗漏”的问题。如果断言失败说明你的填充逻辑有漏洞。6.4 常见错误速查表错误现象可能原因排查方向第一行数字倒序方向初始值搞反检查 direction 的初始值某一行全是0循环范围不对检查 range 的起止参数数字重复换行时没有更新 i检查行末转向逻辑数组越界循环终止条件太宽松检查 while 条件或 for 范围最后一行缺失循环提前退出检查 num n*n 的条件这张表是我自己总结的每次调试的时候对照着看能省不少时间。7. 我的个人经验总结写了这么多最后分享几点我在反复练习蛇形矩阵过程中积累的心得。第一先画图再写代码。这个习惯看起来笨但真的能帮你省很多调试时间。我现在遇到任何矩阵题都会先在纸上画一个 3×3 或 4×4 的格子手动填一遍把规律看清楚再动手。第二边界条件单独处理。不要试图用一套逻辑覆盖所有情况该用 if-else 就用 if-else。代码长一点没关系可读性和正确性更重要。第三多写几种解法。同一道题用逐行填充法写一遍再用模拟行走法写一遍你对题目的理解会完全不一样。面试的时候如果面试官问“还有没有其他思路”你就能从容应对。第四别怕犯错。我写蛇形矩阵至少错了五六次每次都是不同的边界问题。但正是这些错误让我对二维数组的索引控制越来越熟练。现在再写类似的题基本上一次就能过。第五把调试过程记录下来。我现在有一个习惯每次调试超过10分钟的题都会把错误原因和修复方法记在笔记里。时间长了这份笔记就成了我自己的“错题本”复习的时候特别有用。蛇形矩阵这道题说难不难说简单也不简单。它不需要你懂什么高级算法但需要你有清晰的逻辑和细致的边界控制能力。如果你能把这道题吃透再去看其他矩阵模拟题会发现它们都是同一个套路。希望这篇内容能帮你少走一些弯路顺利把这道题拿下。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询