pyhton 螺旋矩阵(指针-矩阵-中等)含源码(二十六)

问题说明(含示例)

问题描述:给定一个正整数 n,生成一个 n x n 的正方形矩阵,矩阵中包含 1 到 n² 的所有元素,且元素按顺时针螺旋顺序排列。

示例输入 输出 解释n = 3 \[1,2,3,8,9,4,7,6,5] 元素从 1 到 9 按顺时针螺旋排列:先右移填充第一行,再下移填充最后一列,再左移填充最后一行,再上移填充第一列,最后填充中心元素n = 1 \[1] 仅 1 个元素,直接返回包含 1 的单元素矩阵n = 2 \[1,2,4,3] 元素 1→2→3→4 按顺时针螺旋排列(右移→下移→左移)

解题关键

核心思路是通过控制边界的螺旋遍历模拟填充过程,利用 "上、下、左、右" 四个边界变量动态收缩范围,按顺时针顺序(右→下→左→上)依次填充元素,直到所有数字(1 到 n²)都被填入矩阵。

具体步骤如下:

  • 初始化 n x n 矩阵(填充 0 占位);
  • 定义四个边界:top(上边界,初始为 0)、bottom(下边界,初始为 n-1)、left(左边界,初始为 0)、right(右边界,初始为 n-1);
  • 从 1 开始填充数字,直到填充完 n²:
    1. 从左到右填充上边界行,完成后上边界上移(top += 1);
    2. 从上到下填充右边界列,完成后右边界左移(right -= 1);
    3. 若上边界未超过下边界,从右到左填充下边界行,完成后下边界下移(bottom -= 1);
    4. 若左边界未超过右边界,从下到上填充左边界列,完成后左边界右移(left += 1);
  • 重复上述步骤,直到所有数字填充完毕。

核心逻辑 + 关键细节

一、核心逻辑:如何模拟顺时针螺旋填充?

通过 "边界收缩" 控制填充范围,将螺旋过程拆解为四次方向填充,每次填充后调整边界,确保不重复填充已有元素:

  1. 方向顺序固定:严格按照 "右→下→左→上" 的顺时针顺序填充,符合螺旋的自然轨迹;
  2. 边界动态调整:每完成一个方向的填充,对应的边界向内收缩(如右移填充完第一行后,上边界下移,避免再次填充该行);
  3. 边界有效性判断 :在填充 "左" 和 "上" 方向时,需判断当前边界是否仍有效(如top <= bottom确保下边界行未被填充过),避免越界或重复填充。
二、关键细节:避坑与优化点
  • 矩阵初始化[[0]*n for _ in range(n)]创建 n x n 矩阵,避免浅拷贝问题(如[[0]*n]*n会导致修改一行全部同步);
  • 循环终止条件 :以 "当前填充数字current <= n²" 为循环条件,确保所有数字都被填充;
  • 方向填充的范围控制
    • 左到右:列从leftright(包含两端);

    • 上到下:行从topbottom(包含两端);

    • 右到左:列从rightleft逆序,步长为 -1);

    • range 函数参数含义 range(right, left - 1, -1) 用于生成从右边界到左边界的逆序列索引,具体参数作用:

      • start = right:起始列索引为当前右边界(最右侧的列);
      • stop = left - 1:终止条件为 "小于 left - 1 时停止"(实际会包含 left 列,因为当 col 减到 left 时,下一次会是 left - 1,此时停止);
      • step = -1:步长为 -1,表示列索引从大到小递减(即 "从右向左" 遍历)。
    • 下到上:行从bottomtop(逆序,步长为 -1);

  • 边界收缩的时机 :每个方向填充完成后立即收缩边界(如右移填充后top += 1),避免下一次填充时重复使用该边界。

对应代码

python 复制代码
def generateMatrix(n: int) -> list[list[int]]:
    # 初始化 n x n 矩阵,用0占位
    matrix = [[0] * n for _ in range(n)]
    # 定义四个边界
    top, bottom = 0, n - 1
    left, right = 0, n - 1
    current = 1  # 从1开始填充
    
    while current <= n * n:
        # 1. 左到右填充上边界行
        for col in range(left, right + 1):
            matrix[top][col] = current
            current += 1
        top += 1  # 上边界下移
        
        # 2. 上到下填充右边界列
        for row in range(top, bottom + 1):
            matrix[row][right] = current
            current += 1
        right -= 1  # 右边界左移
        
        # 3. 右到左填充下边界行(需确保上边界未超过下边界)
        if top <= bottom:
            for col in range(right, left - 1, -1):
                matrix[bottom][col] = current
                current += 1
            bottom -= 1  # 下边界上移
        
        # 4. 下到上填充左边界列(需确保左边界未超过右边界)
        if left <= right:
            for row in range(bottom, top - 1, -1):
                matrix[row][left] = current
                current += 1
            left += 1  # 左边界右移
    
    return matrix

对应的基础知识

实现该算法需掌握以下 Python 基础概念与操作:

  1. 二维列表的创建

    • 语法:[[0]*n for _ in range(n)] 生成 n 行 n 列的矩阵,每行是独立的列表;
    • 注意:避免使用[[0]*n]*n,否则修改一行会导致所有行同步变化(浅拷贝特性)。
  2. 循环与 range 的使用

    • for 循环:用于按方向遍历矩阵的行或列;
    • range 函数:
      • 正向遍历:range(left, right + 1) 覆盖从 left 到 right 的所有列;
      • 逆向遍历:range(right, left - 1, -1) 覆盖从 right 到 left 的所有列(步长为 -1)。
  3. 边界变量的更新

    • 通过top += 1right -= 1等操作动态调整边界,控制填充范围;
    • 边界变量是 "状态标记",直接决定下一次填充的起点和终点。
  4. 条件判断语句

    • if top <= bottomif left <= right 用于判断边界有效性,避免在矩阵填充后期(如只剩一行或一列时)出现重复填充。

对应的进阶知识

该问题涉及螺旋遍历的通用逻辑、复杂度分析与边界处理技巧:

  1. 时间复杂度:O (n²)

    • 矩阵共有 n² 个元素,每个元素仅被填充一次,因此总操作次数为 n²,时间复杂度为 O (n²)。
  2. 空间复杂度:O (n²)

    • 需创建 n x n 的矩阵存储结果,属于输出必要空间,因此空间复杂度为 O (n²)。
  3. 螺旋遍历的通用模型

    • 核心是 "方向循环 + 边界收缩",适用于所有螺旋遍历类问题(如螺旋读取矩阵、螺旋填充矩阵);
    • 方向顺序可灵活调整(如逆时针),只需修改填充的方向顺序和边界收缩逻辑。
  4. 奇偶 n 的差异处理

    • 当 n 为奇数时,最后会剩余中心一个元素(如 n=3 时的 9),通过第四次边界判断(left <= right)后,会进入最后一次左到右填充,自动处理中心元素;
    • 当 n 为偶数时,所有元素会被四次方向填充完整覆盖,无单独中心元素。

编程思维与启示

  1. "拆解问题" 的思维

    • 将复杂的 "螺旋填充" 拆解为 "右→下→左→上" 四个简单的直线填充步骤,通过循环重复这四个步骤,降低问题复杂度;
    • 启示:面对复杂轨迹问题(如蛇形、螺旋),可拆解为有限的基础方向,通过循环实现。
  2. "边界控制" 的重要性

    • 用边界变量(top/bottom/left/right)精准控制填充范围,避免手动计算索引(易出错);
    • 启示:涉及区间或范围的问题(如子数组、矩阵遍历),优先用边界变量标记范围,而非直接操作索引。
  3. "状态同步" 的维护

    • 每次填充后立即更新边界(如填充完上边界后top += 1),确保下一次填充的状态正确;
    • 启示:操作与状态变更需同步,避免因状态滞后导致逻辑错误(如重复填充同一行)。
  4. "条件判断" 的必要性

    • 通过if top <= bottom等判断避免无效填充,适应不同 n 的场景(如 n=1 时无需填充下和左方向);
    • 启示:算法需具备 "鲁棒性",通过条件判断处理边界情况,避免一刀切逻辑。
相关推荐
kebidaixu11 小时前
两轮BMS 防打火策略详解
算法
error:(11 小时前
【系统与实战双精通】VS Code 调试 ROS2 Python 节点与 Launch 系统指南
android·java·python
weigangwin12 小时前
LlamaIndex 第一次试用:别先写 RAG Demo,先验上下文合同
python·ai·agent·rag·检索·llamaindex·观测性
省四收割者12 小时前
一文详解信号完整性(1)
python·嵌入式硬件·数学建模·信息与通信·信号处理·智能硬件
wabs66612 小时前
关于动态规划【力扣1035.不相交的线和53.最大子数组和的思考】
算法·leetcode·动态规划
退休倒计时12 小时前
【每日一题】LeetCode 199. 二叉树的右视图 TypeScript
算法·leetcode·typescript
可编程芯片开发12 小时前
通过MATLAB实现PID控制器,积分分离控制器以及滑模控制器
算法
kebidaixu12 小时前
两轮BMS 短路保护策略详解
算法
ai生成式引擎优化技术13 小时前
从知识连接到智能组织:WSaiOS认知网络的理论框架与系统设计摘要
网络·python·plotly·django·pygame
用户83562907805113 小时前
使用 Python 保护和取消保护 Excel 工作表和工作簿
后端·python