(19)LeetCode 54. 螺旋矩阵

LeetCode 54. 螺旋矩阵(顺时针遍历)

题目描述

给你一个 m 行 n 列的矩阵 matrix,请按照 顺时针螺旋顺序,返回矩阵中的所有元素。

示例 1:

复制代码
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]

示例 2:

复制代码
输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]

算法思路

我们可以把螺旋遍历看作一个人在矩阵中沿顺时针方向行走,遇到边界或已经走过的格子就右转。这样只要模拟这个行走过程,就能按顺序访问所有元素。

关键点

  • 方向控制 :使用方向数组 dx[] 和 dy[] 表示四个方向(右、下、左、上),顺序严格按顺时针排列。
  • 访问标记 :用布尔数组 st 记录每个位置是否已被访问,避免重复。
  • 转向条件:每次尝试向前走一步,如果下一步越界或已访问,则立刻顺时针旋转 90°,再重新计算下一步。

模拟过程

  1. 从左上角 (0, 0) 出发,初始方向为 向右。
  2. 每走到一个格子,就将其值加入结果数组,并标记为已访问。
  3. 根据当前方向计算下一个格子的坐标。
  4. 如果下一个格子不合法(越界或已访问),则顺时针改变方向,重新计算下一个格子。
  5. 重复步骤 2~4,直到走完所有格子(共 m * n 个)。

代码实现(C++)

cpp 复制代码
class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        vector<int> res;                     // 存储结果
        int n = matrix.size();               // 行数
        if (!n) return res;                  // 空矩阵直接返回
        int m = matrix[0].size();            // 列数

        // 方向数组:右、下、左、上(顺时针)
        int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};
        
        // 访问标记数组
        vector<vector<bool>> st(n, vector<bool>(m, false));

        // i 记录已访问元素个数,x,y 为当前位置,d 为当前方向索引
        for (int i = 0, x = 0, y = 0, d = 0; i < n * m; i++) {
            res.push_back(matrix[x][y]);     // 记录当前元素
            st[x][y] = true;                 // 标记已访问

            // 尝试按当前方向走一步
            int a = x + dx[d], b = y + dy[d];
            // 如果下一步越界或已访问,则右转
            if (a < 0 || a >= n || b < 0 || b >= m || st[a][b]) {
                d = (d + 1) % 4;             // 顺时针旋转方向
                a = x + dx[d];
                b = y + dy[d];
            }

            // 移动到下一个位置
            x = a;
            y = b;
        }

        return res;
    }
};

复杂度分析

  • 时间复杂度 :O(m * n),每个元素恰好被访问一次。
  • 空间复杂度 :O(m * n),额外使用了一个与矩阵同等大小的布尔标记数组。
    (如果要求 O(1) 空间,可以使用边界收缩法,但本题无此限制,此写法更易理解。)

运行示例

以矩阵

复制代码
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]

为例,模拟过程如下:

步骤 当前位置 方向 动作
1 (0,0)=1 右 记录1,向右
2 (0,1)=2 右 记录2,向右
3 (0,2)=3 右 记录3,下一步越界 → 转向下
4 (1,2)=6 下 记录6,向下
5 (2,2)=9 下 记录9,下一步越界 → 转向左
6 (2,1)=8 左 记录8,向左
7 (2,0)=7 左 记录7,下一步越界 → 转向上
8 (1,0)=4 上 记录4,向上
9 (1,1)=5 上 记录5,全部遍历结束

最终结果:[1,2,3,6,9,8,7,4,5],符合预期。


总结

  • 使用 方向数组 + 访问标记 模拟螺旋行走,逻辑直观,不易出错。
  • 每次尝试前进,遇到障碍就右转,保证了螺旋顺序。
  • 该解法适用于任意 m × n 矩阵(包括非方阵)。
相关推荐
Cccp.1233 小时前
【leetcode】(七)前缀树和贪心算法
数据结构·leetcode·贪心算法
千里码aicood3 小时前
基于CART算法的图书分类系统设计与实现
数据库·算法·分类
做cv的小昊3 小时前
【World Model】π0.5:a Vision-Language-Action Model with Open-World Generalization
人工智能·算法·机器学习·大模型·多模态·vla·世界模型
لا معنى له4 小时前
World-In-World: World Models in a Closed-Loop World
算法
Discipline10296 小时前
尼泊尔河流流量:天气驱动的预测与高流量风险
人工智能·算法
XuCoder6 小时前
改一个数,右边全得重算,这题怎么扛住两万次查询
算法
小羊没烦恼!7 小时前
在Scrum中实施敏捷建模
java·开发语言·windows·算法·c#
weixin_307779137 小时前
基于睿擎工业开发平台的预训练视觉模型轻量化适配与低代码部署优化
开发语言·算法
hold?fish:palm7 小时前
45 二叉树的右视图
开发语言·c++·算法