(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 矩阵(包括非方阵)。
相关推荐
GoAI2 小时前
DeepSeek Harness Memory (一)主流记忆插件总结
后端·算法·面试
DFT计算杂谈2 小时前
可DIY布里渊区图像绘制编辑器
人工智能·机器学习·语言模型·矩阵·编辑器
Pniubi3 小时前
力扣54.螺旋矩阵
算法·leetcode·矩阵
choumou_M5 小时前
算法_1:由浅入深学习快速排序QuickSort
学习·算法·排序算法
Coder_Shenshen6 小时前
罗克韦尔ACD工程归档离线变量树解析
算法·c#
心仪久了会沦陷7 小时前
C语言数据结构入门——树与二叉树详解:概念、堆实现与链式遍历
c语言·数据结构·算法
小此方7 小时前
[算法实战论:动态规划]背包问题概念,01不满背包问题,01满背包问题,背包问题的滚动数组空间优化
算法·动态规划
悠仁さん9 小时前
【C++】哈希表
c++·算法·散列表
地平线开发者9 小时前
点云算法整理与常用计算模块:从数据到模型,再到工程与量化
算法·自动驾驶