(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 矩阵(包括非方阵)。
相关推荐
Frostnova丶1 小时前
(18)LeetCode 73. 矩阵置零
算法·leetcode·矩阵
冻柠檬飞冰走茶1 小时前
PTA基础编程题目集 7-11 分段计算居民水费(C语言实现)
c语言·开发语言·算法
得物技术1 小时前
推荐系统体验的数字化突破:得物自动化评测平台的技术实践|AICon 文章整理
算法·架构·llm
VALENIAN瓦伦尼安教学设备2 小时前
转子/行星/平行轴齿轮箱综合故障模拟实验台可复现常见机械问题
大数据·数据库·人工智能·嵌入式硬件·算法
rannn_1112 小时前
【力扣hot100】哈希表专题——从两数之和到最长连续序列
java·算法·leetcode·哈希
小保CPP2 小时前
OpenCV C++基于极值区域滤波算法的场景文本检测(OCR)
c++·人工智能·opencv·算法·计算机视觉·ocr
来一碗刘肉面3 小时前
字符串模式匹配(朴素模式匹配算法与KMP算法)
数据结构·算法
go不是csgo3 小时前
从模板到五道 LeetCode:完全背包的 Golang 教学笔记
笔记·leetcode·golang
dyxal3 小时前
eˣ 的泰勒展开式:从“化繁为简”到“万物统一”的微积分之美
算法