问题描述
蛇形填充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 = 3、n = 4、n = 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 阶方阵来存储填充的数字,通过行、列索引访问元素。
变量操作 -
定义并初始化多种变量: - 用 top、bottom、left、right 界定方阵各层填充边界,初始值对应方阵上下左右范围,填充中不断更新。 - 以 num 作为计数变量,从1开始随填充递增,直至达到 n * n。
循环结构 -
while 循环控制整体填充流程,依据 num <= n * n 条件确保方阵完整填充。 - 多次运用 for 循环实现不同方向填充:从右上到右下、右下到左下、左下到左上、左上到右上,通过调整循环范围及索引准确填充对应位置。
索引与范围运用 -
灵活设置 for 循环范围参数实现反向遍历,结合行、列索引精准定位方阵元素进行填充。
变量更新 -
完成各方向填充后,及时更新边界变量(如 top、bottom、left、right)界定下一层范围,同时递增计数变量 num 保证填充数字顺序正确。 这些知识点协同配合,实现了蛇形填充 n 阶方阵的功能。