题目 (LeetCode题目链接)
给你一个正整数 n n n ,生成一个包含 1 1 1 到 n 2 n^2 n2 所有元素,且元素按顺时针顺序螺旋排列的 n × n n \times n n×n 正方形矩阵 matrix。
python 知识点
[[0] * n for _ in range(n)]
是初始化二维
n
×
n
n \times n
n×n矩阵的简洁方法。
• 在 Python 中,_ 通常用作占位符变量名,表示“这个变量的值我不关心”。
• 在这个例子中,for _ in range(n) 中的 _ 表示循环变量的值不需要被使用。
range(start, stop, step)
range() 函数用法
• start:起始值,序列从这个值开始。
• stop:终止值,序列到达(但不包括)这个值。
• step:步长,表示每次递增或递减的值。
解答
为什么一开始就定义4个边界?4个边界的意义?
- 覆盖所有方向的填充
螺旋填充涉及四个方向(从左到右,从上到下,从右到左,从下到上),每个方向都需要一个明确的边界来控制填充范围:
• 从左到右填充时,用 left 和 right 确定列的范围。
• 从上到下填充时,用 top 和 bottom 确定行的范围。
• 从右到左填充时,用 right 和 left 确定列的范围。
• 从下到上填充时,用 bottom 和 top 确定行的范围。 - 控制动态收缩
每次填充后,相应边界会更新,缩小矩阵的有效区域。例如:
• 填充完第 0 行后,top 增加 1(上边界下移),表示第 0 行不再需要填充。
• 填充完第 n-1 列后,right 减少 1(右边界左移),表示第 n-1 列不再需要填充。
• 填充完第 n-1 行后,bottom 减少 1(下边界上移),表示第 n-1 行不再需要填充。
• 填充完第 0 列后,left 增加 1(左边界右移),表示第 0 列不再需要填充。 - 停止条件的判断
通过边界定义,可以方便地检查什么时候完成填充:
• 如果 top > bottom 或 left > right,说明填充完成,因为所有有效区域都被覆盖。
总结: 虽然一开始填充只用到 top 和 left,但为了整个填充过程逻辑清晰、代码简洁,提前定义四个边界 (top, bottom, left, right) 是必要的。
复杂度分析
- 时间复杂度:
• 总共有 n 2 n^2 n2 个数字需要填充,每个数字填充一次,时间复杂度为 O ( n 2 ) O(n^2) O(n2) 。 - 空间复杂度:
• 仅使用了常数级别的辅助变量(边界控制变量和填充数字),因此空间复杂度为 O ( 1 ) O(1) O(1)(不包括输出矩阵的空间)。
代码实现
def generateMatrix(self, n: int) -> List[List[int]]:
matrix = [[0] * n for _ in range(n)] # 初始化 n x n 矩阵
top, bottom, left, right = 0, n - 1, 0, n - 1 # 定义边界
num = 1 # 填充的数字从 1 开始
while top <= bottom and left <= right:
# 从左到右填充
for col in range(left, right + 1):
matrix[top][col] = num
num += 1
top += 1 # 上边界下移
# 从上到下填充
for row in range(top, bottom + 1):
matrix[row][right] = num
num += 1
right -= 1 # 右边界左移
# 从右到左填充
if top <= bottom: # 确保还在有效范围内, 好像不用也可以
for col in range(right, left - 1, -1):
matrix[bottom][col] = num
num += 1
bottom -= 1 # 下边界上移
# 从下到上填充
if left <= right: # 确保还在有效范围内, 好像不用也可以,直接利用range(1, 0)是空的
for row in range(bottom, top - 1, -1):
matrix[row][left] = num
num += 1
left += 1 # 左边界右移
return matrix