54. 螺旋矩阵

54. 螺旋矩阵

!abstract 一句话本质 就是模拟"顺时针走螺旋"的过程,不是真的有数学公式,而是"沿当前方向走,撞墙(越界或已访问)就右转 90°",走满 m·n 步停。
!quote 链接

题目

给一个 m×n 矩阵,按顺时针螺旋顺序返回所有元素(从左上角出发,右→下→左→上 循环)。

思路(从暴力到最优)

最直接的想法:模拟人走螺旋的过程。

  • 维护一个"当前方向",用方向向量 [[0,1],[1,0],[0,-1],[-1,0]] 分别表示 右、下、左、上。
  • 走到下一格之前,先看"按当前方向走会不会撞墙":
    • 越界(出矩阵)
    • 已访问过
  • 撞墙就 di = (di + 1) % 4 右转,再走。
  • 走满 m·n 步就停。

怎么标记"已访问"?两个办法:

  1. 原地修改 :把访问过的格子设成一个哨兵值(如 Infinity),空间 O(1) 但破坏原矩阵。← 本解法
  2. 额外 visited 矩阵:空间 O(m·n),不破坏原矩阵。

另一种写法 ------ 收缩边界法 : 维护 top/bottom/left/right 四个指针,每走完一行/列就收缩对应边界。优点是不破坏原矩阵、空间 O(1),而且对"生成螺旋矩阵"(螺旋矩阵 II)更自然。缺点是四个方向要分别写循环,代码长一点。

收缩边界法详解

四个边界含义:

  • top:当前还没处理过的最上行
  • bottom:当前还没处理过的最下行
  • left:当前还没处理过的最左列
  • right:当前还没处理过的最右列

遍历顺序固定为:

  1. 从左到右遍历 top 行,然后 top++
  2. 从上到下遍历 right 列,然后 right--
  3. 检查 top <= bottom,再从右到左遍历 bottom 行,然后 bottom--
  4. 检查 left <= right,再从下到上遍历 left 列,然后 left++

每轮循环后,有效矩阵向内收缩一圈。步骤 3 和 4 必须先检查边界再遍历,因为单行或单列矩阵走完前两步之后,已经不存在可走的另一边了。

javascript 复制代码
var spiralOrder2 = function(matrix) {
    const m = matrix.length, n = matrix[0].length;
    let top = 0, bottom = m - 1, left = 0, right = n - 1;
    const ans = [];

    while (top <= bottom && left <= right) {
        // 向右:top 行,left → right
        for (let j = left; j <= right; j++) ans.push(matrix[top][j]);
        top++;

        // 向下:right 列,top → bottom
        for (let i = top; i <= bottom; i++) ans.push(matrix[i][right]);
        right--;

        // 向左:bottom 行,right → left
        if (top <= bottom) {
            for (let j = right; j >= left; j--) ans.push(matrix[bottom][j]);
            bottom--;
        }

        // 向上:left 列,bottom → top
        if (left <= right) {
            for (let i = bottom; i >= top; i--) ans.push(matrix[i][left]);
            left++;
        }
    }

    return ans;
};

时间复杂度同样是 O(m·n),额外空间 O(1),并且不修改原矩阵。

关键卡点

!warning 我当时卡在这

  • 方向向量顺序:必须是 右→下→左→上(顺时针),顺序错了输出全乱。
  • 越界检查必须放在"已访问检查"前面 :如果 x, y 已越界,再读 matrix[x][y] 在某些语言会直接报错(JS 里是 undefined,侥幸不崩但是坏习惯)。
  • 1×n 矩阵的隐患 :循环靠 k < m*n 卡次数终止,最后一格转弯后的越界坐标实际没被用到。能过题,但要意识到是"次数卡得准"救了你。
  • 本题是看题解后写出来的,对"收缩边界法"还不熟,下次复习时要手写一遍收缩边界法。

代码

javascript 复制代码
var spiralOrder = function(matrix) {
    // 方向向量:右、下、左、上(顺时针)
    const DIR = [[0, 1], [1, 0], [0, -1], [-1, 0]];
    const m = matrix.length, n = matrix[0].length;
    const ans = [];
    let i = 0, j = 0, di = 0;

    for (let k = 0; k < m * n; k++) {
        ans.push(matrix[i][j]);
        matrix[i][j] = Infinity;  // 标记已访问(原地修改)

        // 预判下一格
        const x = i + DIR[di][0];
        const y = j + DIR[di][1];

        // 越界 || 已访问 → 右转
        if (x < 0 || x >= m || y < 0 || y >= n || matrix[x][y] === Infinity) {
            di = (di + 1) % 4;
        }

        i += DIR[di][0];
        j += DIR[di][1];
    }
    return ans;
};

复杂度

  • 时间:O(m·n),每个格子访问一次。
  • 空间:O(1)(不算答案数组;原地修改的代价是破坏输入)。

一句话记忆点

!tip 下次看到类似题 螺旋遍历 → 方向向量 右下左上 + 撞墙右转 (di+1)%4;不能改原矩阵就上收缩边界法(top/bottom/left/right 四指针)。

相似题 / 套用模板

  • 59. 螺旋矩阵 II(生成螺旋矩阵)→ 收缩边界法更好写
  • 73. 矩阵置零(同专题,矩阵原地操作)
  • 方向向量 + 撞墙转向 模板可迁移到所有"按固定方向走、遇阻转向"的模拟题

复习记录

2026-08-11 第 1 次复习

结果:未通过 ❌(阶段 1→0,重置为 0,3 天后复习 2026-08-14)

记得牢:

  • 代码逻辑正确,用收缩边界法 AC(四边界 l/r/t/b + 每步收缩 + break 判越界),用 [[1,2,3],[4,5,6],[7,8,9]] 验证输出 [1,2,3,6,9,8,7,4,5] 正确。
  • 客观上完成了"手写收缩边界法"的要求(虽然自己没意识到)。

需要加强:

  • 方法认知混淆 :写了收缩边界法却以为是"模拟",分不清两种写法------①方向向量模拟法(指针+方向变量 di+visited 标记/原地改);②收缩边界法(四边界+收缩,无需 visited、无需方向变量)。必须能识别自己写的是哪种。
  • 不独立:自述看题解写出,复习要求凭记忆独立完成。
  • 复杂度记法 :把 O(m·n) 写成 O(N²)------量级直觉有部分道理(两维相乘),但记法不规范;O(N²) 特指单变量平方,只有方阵(m=n=N)才成立。空间方面质疑了"输出数组算不算额外空间"------约定是输出数组不计入额外空间,所以额外空间 O(1);省下的是 visited 矩阵那 O(m·n)。
  • 下次复习重点:独立默写收缩边界法 + 准确说出 O(m·n) 时间 / O(1) 额外空间 + 能区分两种模拟写法。
相关推荐
灯澜忆梦10 小时前
【面向对象编程C++】| 基础语法
java·c++·算法
小蒋观天下10 小时前
专项方案:大场景港口AI安防、多干扰环境下的算法调优与落地实操
人工智能·深度学习·算法·安全·机器学习·计算机视觉·ai大模型
Evand J10 小时前
【电机滤波例程5】渐消因子自适应扩展卡尔曼滤波(EKF),MATLAB。PMSM负载突变下的状态估计。附下载链接
算法·matlab
H.莓飛10 小时前
【数据结构】二叉树_OJ题
linux·开发语言·数据结构·算法
好想像大佬一样能够ak所有11 小时前
Leetcode35.搜索插入位置
数据结构·算法·leetcode
aqiu11111111 小时前
【C++算法打怪专栏】LeetCode 165. 比较版本号(双指针与字符串流法)
c++·算法·leetcode
黄金龙PLUS11 小时前
如何基于置换算法来设计对称加密算法
算法·网络安全·密码学·哈希算法·同态加密
不会就选b11 小时前
算法日常・每日刷题--<动态规划>14
算法
赛博守夜人12 小时前
跨境业务与出海合规之九:海外买量投放与营销虚假流量(Ad Fraud):跨国机房群控与归因欺诈识别算法
算法·安全
镜子AI14 小时前
教培机构AI推荐系统实战:概念漂移检测算法——为什么“去年有效的推荐今年可能失效“
人工智能·算法