(19)LeetCode 54. 螺旋矩阵

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

题目描述

给你一个 mn 列的矩阵 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 矩阵(包括非方阵)。
相关推荐
en.en..1 小时前
Linux fork() 工作原理
数据结构·算法
地平线开发者2 小时前
bevformer算法模型详细解读
算法
liliangcsdn2 小时前
ICIR权重矩阵如何加权标准化为综合因子
算法
SDWAN_Cheap2 小时前
SD-WAN智能选路技术的算法与实现机制
算法·php·sdwan
不会就选b3 小时前
数据结构之树&&二叉树(二)
数据结构·算法
渡之3 小时前
ArduPilot (APM)滤波器之SlewLimiter 深度解析
算法
zander2584 小时前
LeetCode 1143. 最长公共子序列
开发语言·python·算法
Sumerking4 小时前
llc_control.c 专项评审(v3 更新版)
c语言·开发语言·算法·obc
L小航呀4 小时前
代码随想录刷题 Day16
leetcode·面试
软行4 小时前
LeetCode 每日一题 3876. 构造奇偶一致的数组 II
c++·算法·leetcode