【Hot 100 刷题计划】 LeetCode 54. 螺旋矩阵 | C++ 模拟法题解

LeetCode 54. 螺旋矩阵 | C++ 边界收缩模拟法题解

📌 题目描述

题目级别:中等

给你一个 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]


💡 解题思路:四指针边界收缩 (剥洋葱模型)

这道题没有复杂的算法套路,拼的就是纯粹的代码模拟能力。我们可以把顺时针遍历矩阵想象成"剥洋葱",一层一层地从外向内剥。

为了精准控制遍历的范围,我们设立四个边界指针:

  • u (up):上边界,初始为 0
  • d (down):下边界,初始为 m - 1
  • l (left):左边界,初始为 0
  • r (right):右边界,初始为 n - 1

核心运作机制:

每一圈的遍历严格按照 "向右 -> 向下 -> 向左 -> 向上" 的顺序进行:

  1. 向右遍历 (顶边) :从 l 走到 r。遍历完后,最上面这一行就被剥掉了,所以上边界下移 u++。
  2. 向下遍历 (右边) :从 u 走到 d。遍历完后,最右边这一列就被剥掉了,所以右边界左移 r--。
  3. 向左遍历 (底边) :从 r 走到 l。遍历完后,最下面这一行就被剥掉了,所以下边界上移 d--。
  4. 向上遍历 (左边) :从 d 走到 u。遍历完后,最左边这一列就被剥掉了,所以左边界右移 l++。

⚠️ 致命避坑点:

由于每次剥完一条边,我们都会收缩边界,这就导致在进行"向左"和"向上"遍历时,可能剩下的矩阵已经是一条直线(没有宽度或高度了)。因此,在反向遍历前,必须严格检查 u <= d 和 l <= r,否则会发生重复打印!


💻 C++ 代码实现

cpp 复制代码
class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        int m = matrix.size();
        if (m == 0) return {};
        int n = matrix[0].size();

        // 定义上下左右四个边界
        int u = 0, d = m - 1;
        int l = 0, r = n - 1;

        vector<int> res;

        // 当矩阵还有剩余层数时,继续循环
        while (l <= r && u <= d) {
            
            // 1. 从左到右,遍历最上面一行
            for (int i = l; i <= r; i++) res.push_back(matrix[u][i]);
            u++; // 上边界收缩(下移)

            // 2. 从上到下,遍历最右边一列
            for (int j = u; j <= d; j++) res.push_back(matrix[j][r]);
            r--; // 右边界收缩(左移)

            // 3. 从右到左,遍历最下面一行
            // 必须检查上下边界是否还合法,防止在单行矩阵中重复遍历
            if (u <= d) {
                for (int i = r; i >= l; i--) res.push_back(matrix[d][i]);
            }
            d--; // 下边界收缩(上移)
            
            // 4. 从下到上,遍历最左边一列
            // 必须检查左右边界是否还合法,防止在单列矩阵中重复遍历
            if (l <= r) {
                for (int j = d; j >= u; j--) res.push_back(matrix[j][l]);
            }
            l++; // 左边界收缩(右移)
        }

        return res;
    }
};
相关推荐
你怎么知道我是队长5 小时前
C++零基础第3周:if/else、switch、for/while/do-while 控制流完全指南(附20段可运行代码+避坑清单)
java·开发语言·c++
青少儿编程课堂5 小时前
蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级:倍增法求最近公共祖先LCA解析
c++·python·算法·bfs·信息学竞赛
雷✘6 小时前
C++ 类与对象的初始化机制、成员访问边界与拷贝优化
java·网络·c++
努力实干7 小时前
简单工厂模式(Simple Factory Pattern)——C++
开发语言·c++·简单工厂模式
東隅已逝,桑榆非晚8 小时前
算法2. 双指针法-复写零
c++·笔记·学习·算法
布莱克6058 小时前
C++ 中堆和栈的区别详解
开发语言·c++·栈·堆
释厄6238 小时前
三角基底律——矩阵3x6 是所有三角形的基底·3D中高就是边
线性代数·3d·矩阵
誰能久伴不乏9 小时前
用 UDP 做一条“可靠“的控制通道
c++·qt·网络协议·udp
十五年专注C++开发9 小时前
FlatBuffers: 一个高效的零拷贝二进制序列化库
c++·序列化·反序列化·flatbuffers
xys_67810 小时前
深挖C++:C++入门基础
开发语言·c++