青训营X豆包MarsCode 技术训练营第一课 | 豆包MarsCode AI刷题

155 阅读6分钟

问题描述

蛇形填充n阶方阵

小U面临一个有趣的任务:在一个 𝑛 × 𝑛 n×n 的方阵中填入 1 1 到 𝑛 × 𝑛 n×n 这些数字,并要求按照蛇形顺序从右上角开始,沿着方阵的边界顺时针进行填充。蛇形填充的特殊排列方式使得每一层数字呈现出波浪形的排列方式。

例如,当 n=4 时,方阵应如下所示:

10 11 12  1
9 16 13  2
8 15 14  3
7  6  5  4

思考

1. 问题分析

  • 目标是在 n×n 的方阵中按照特定的蛇形顺序填充数字,从右上角开始,沿方阵边界顺时针以波浪形排列方式填充 1 到 n×n 的整数。通过给定的不同规模 n 的测试样例,如 n = 3n = 4n = 5 等,可以清晰地看到期望的输出方阵样式,每个方阵都遵循蛇形填充规则。

2. 解题思路

  • 方阵初始化:首先创建一个 n 行 n 列的二维列表 matrix,并将所有元素初始化为 0,为填充数字做准备。这一步通过列表推导式 [[0] * n for _ in range(n)] 实现,简单而高效地构建了方阵的基本结构。
  • 方向定义:定义了一个包含四个元组的列表 directions,分别为 (0, 1)(右)、(1, 0)(下)、(0, -1)(左)、(-1, 0)(上),用于表示在方阵中移动的四个方向。这些方向元组明确了坐标的偏移量,方便后续计算下一个填充位置。
  • 初始设置:设定初始位置为方阵的右上角,即横坐标 x = 0,纵坐标 y = n - 1,同时将初始方向索引 direction_index 设为 0,对应着向右的方向。这一系列设置确定了填充的起始点和起始方向。
  • 数字填充过程:使用一个从 1 到 n×n 的循环来填充数字。在每次循环中,先将当前数字填充到当前位置 (x, y) 的矩阵元素中。接着通过当前方向索引从 directions 列表中获取坐标偏移量,计算下一个位置 (next_x, next_y)。然后进行关键的方向判断,若下一个位置超出方阵范围或该位置已被填充(不为 0),则通过改变方向索引 direction_index(取模运算实现循环切换方向)来调整方向,并重新计算下一个位置。最后更新当前位置为下一个合法位置,继续下一轮填充,直至所有数字填充完毕。

代码结构

初始化部分

matrix = [[0] * n for _ in range(n)] top, bottom, left, right = 0, n - 1, 0, n - 1 num = 1

首先,通过列表推导式创建了一个 n 行 n 列的二维列表 matrix,并将所有元素初始化为 0,这是用于存储最终填充好数字的方阵。 接着,定义了四个变量 top、bottom、left 和 right,分别表示方阵当前层的上边界、下边界、左边界和右边界。初始时,上边界 top 为 0,下边界 bottom 为 n - 1,左边界 left 为 0,右边界 right 为 n - 1,它们将随着填充过程不断更新,以确定每一层的填充范围。 最后,初始化变量 num 为 1,用于记录要填充的数字,从 1 开始逐步递增直到 n * n。

填充循环部分

`

while num <= n * n: # 从右上到右下填充 
for i in range(right, left - 1, -1): matrix[top][i] = num num += 1 top += 1 
# 从右下到左下填充 
for i in range(top, bottom + 1): matrix[i][left] = num num += 1 left += 1 
# 从左下到左上填充 
for i in range(left, right + 1): matrix[bottom][i] = num num += 1 bottom -= 1 
# 从左上到右上填充 
for i in range(bottom, top - 1, -1): matrix[i][right] = num num += 1 right -= 1

整个填充过程是在一个 while 循环中进行的,只要要填充的数字 num 不超过 n * n,就会持续循环填充。 在每次循环中,按照蛇形填充的顺序,分四个步骤进行填充:

从右上到右下填充:

通过一个 for 循环,从当前层的右边界 right 开始,向左递减到左边界 left(注意这里的范围设置 range(right, left - 1, -1),是为了能取到左边界的值),将数字 num 依次填充到方阵的上边界 top 这一行对应的列位置上。每填充一个数字,num 就递增 1,填充完这一行后,上边界 top 向下移动一格(top += 1),准备填充下一层。

从右下到左下填充:

接着,另一个 for 循环从当前层的上边界 top(已经更新过)开始,向下递增到下边界 bottom,将数字 num 依次填充到方阵的左边界 left 这一列对应的行位置上。同样,每填充一个数字,num 递增 1,填充完这一列后,左边界 left 向右移动一格(left += 1)。

从左下到左上填充:

再通过一个 for 循环,从当前层的左边界 left(已经更新过)开始,向右递增到右边界 right,将数字 num 依次填充到方阵的下边界 bottom 这一行对应的列位置上。每填充一个数字,num 递增 1,填充完这一行后,下边界 bottom 向上移动一格(bottom -= 1)。

从左上到右上填充:

最后一个 for 循环从当前层的下边界 bottom(已经更新过)开始,向上递减到上边界 top(注意这里的范围设置 range(bottom, top - 1, -1),是为了能取到上边界的值),将数字 num 依次填充到方阵的右边界 right 这一列对应的行位置上。每填充一个数字,num 递增 1,填充完这一列后,右边界 right 向左移动一格(right -= 1)。

返回结果部分

return matrix

用到的知识点

数据结构 -

利用二维列表(矩阵)创建 n 阶方阵来存储填充的数字,通过行、列索引访问元素。

变量操作 -

定义并初始化多种变量: - 用 topbottomleftright 界定方阵各层填充边界,初始值对应方阵上下左右范围,填充中不断更新。 - 以 num 作为计数变量,从1开始随填充递增,直至达到 n * n

循环结构 -

while 循环控制整体填充流程,依据 num <= n * n 条件确保方阵完整填充。 - 多次运用 for 循环实现不同方向填充:从右上到右下、右下到左下、左下到左上、左上到右上,通过调整循环范围及索引准确填充对应位置。

索引与范围运用 -

灵活设置 for 循环范围参数实现反向遍历,结合行、列索引精准定位方阵元素进行填充。

变量更新 -

完成各方向填充后,及时更新边界变量(如 topbottomleftright)界定下一层范围,同时递增计数变量 num 保证填充数字顺序正确。 这些知识点协同配合,实现了蛇形填充 n 阶方阵的功能。