每日算法练习: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]

提示:

  • m == matrix.length(行数)
  • n == matrix[i].length(列数)
  • 1 <= m, n <= 10
  • -100 <= matrix[i][j] <= 100

解题思路

核心思路:按层模拟,边界收缩

螺旋遍历的本质是按顺序绕圈:

  1. 从左到右(顶行)
  2. 从上到下(右列)
  3. 从右到左(底行)
  4. 从下到上(左列)

走完一圈后,收缩边界(上边界 + 1,下边界 - 1,左边界 + 1,右边界 - 1),继续遍历内层,直到所有元素都被访问。

最优解法:四边界 + 循环判定

核心变量(四个边界):

  • top:上边界(行号,初始 0)
  • bottom:下边界(行号,初始matrix.length-1)
  • left:左边界(列号,初始 0)
  • right:右边界(列号,初始matrix[0].length-1)

逻辑步骤:

  1. 遍历顶行:从 left 到 right,遍历完 top++
  2. 遍历右列:从 top 到 bottom,遍历完 right--
  3. 遍历底行:从 right 到 left,遍历完 bottom--
  4. 遍历左列:从 bottom 到 top,遍历完 left++
  5. 循环终止 :当 top > bottom 或 left > right 时,停止遍历。

代码实现

复制代码
class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> res = new ArrayList<>();
        if (matrix == null || matrix.length == 0) {
            return res;
        }

        // 1. 定义四个边界
        int top = 0;
        int bottom = matrix.length - 1;
        int left = 0;
        int right = matrix[0].length - 1;

        // 2. 循环遍历,直到边界相遇
        while (top <= bottom && left <= right) {
            // ① 从左到右:遍历顶行
            for (int i = left; i <= right; i++) {
                res.add(matrix[top][i]);
            }
            top++; // 上边界下移

            // ② 从上到下:遍历右列
            // 需判断是否还有行可遍历(防止只有一行的情况)
            if (top > bottom) break;
            for (int i = top; i <= bottom; i++) {
                res.add(matrix[i][right]);
            }
            right--; // 右边界左移

            // ③ 从右到左:遍历底行
            // 需判断是否还有列可遍历(防止只有一列的情况)
            if (left > right) break;
            for (int i = right; i >= left; i--) {
                res.add(matrix[bottom][i]);
            }
            bottom--; // 下边界上移

            // ④ 从下到上:遍历左列
            if (top > bottom) break;
            for (int i = bottom; i >= top; i--) {
                res.add(matrix[i][left]);
            }
            left++; // 左边界右移
        }

        return res;
    }
}

代码详解

1. 边界初始化

  • top = 0:初始指向第一行。
  • bottom = matrix.length - 1:初始指向最后一行。
  • left = 0:初始指向第一列。
  • right = matrix[0].length - 1:初始指向最后一列。

2. 主循环

while (top <= bottom && left <= right):保证每次循环都是一个有效的矩形区域。

3. 四个方向遍历(重点!)

① 从左到右(顶行)
  • 遍历范围:[top][left] → [top][right]
  • 遍历结束后:top++(这一行已经走完,下移一层)
② 从上到下(右列)
  • 必须先判断 top > bottom :
    • 比如矩阵是 [1,2,3](一行),遍历完顶行后 top=1,此时 top > bottom,直接退出,避免重复添加。
  • 遍历范围:[top][right] → [bottom][right]
  • 遍历结束后:right--(这一列已经走完,左移一层)
③ 从右到左(底行)
  • 必须先判断 left > right :
    • 比如矩阵是 [[1],[2],[3]](一列),上两步走完后 right=0,此时 left > right,直接退出。
  • 遍历范围:[bottom][right] → [bottom][left]
  • 遍历结束后:bottom--(这一行已经走完,上移一层)
④ 从下到上(左列)
  • 必须先判断 top > bottom:防止行越界。
  • 遍历范围:[bottom][left] → [top][left]
  • 遍历结束后:left++(这一列已经走完,右移一层)

4. 防越界判断(面试加分项!)

在遍历右列、底行、左列之前,都要再次判断边界是否交叉。

  • 例如:如果矩阵只有一行(m=1),遍历完顶行 后,top++ 会导致 top > bottom,后续的循环直接跳过,不会出错。

示例模拟

以 示例 1 [[1,2,3],[4,5,6],[7,8,9]] 为例:

  1. 初始状态 :top=0, bottom=2, left=0, right=2
    • 顶行(0 行):添加 1,2,3 → top=1
    • 右列(2 列):添加 6,9 → right=1
    • 底行(2 行):添加 8,7 → bottom=1
    • 左列(0 列):添加 4 → left=1
  2. 当前状态 :top=1, bottom=1, left=1, right=1(中心只剩一个 5)
    • 进入循环,top<=bottom 且 left<=right 成立。
    • 顶行(1 行):添加 5 → top=2
    • 此时判断 top > bottom (2>1),break,循环结束。
  3. 最终结果 :[1,2,3,6,9,8,7,4,5],完美匹配!

复杂度分析

指标 复杂度 说明
时间复杂度 O(mn) 每个元素只遍历一次,遍历次数等于矩阵元素总数
空间复杂度 O(1) 除了结果列表,只使用了常数个变量(边界)

高频易错点总结

  1. 忘记判断边界 :遍历右列、底行、左列前,必须加 if 判断,否则会出现元素重复 或数组越界错误。
  2. 方向顺序错误 :必须严格遵循左→右 → 上→下 → 右→左 → 下→上的顺序。
  3. 边界更新时机 :先遍历,后更新边界(top++ 等操作必须在遍历完那一圈之后做)。
  4. 矩阵形状 :
    • 处理 1xN (一行)或 Nx1 (一列)的矩阵时,代码能自动处理,因为边界判断会触发 break。

总结

这道题的核心是 **「边界收缩」**。

  • 不要死记硬背,只要记住:走一圈,四个方向各走一遍,然后把包围圈往里缩一点,继续走。
  • 这道题的代码模板非常通用,面试中如果遇到螺旋矩阵 II(LeetCode 59),只需要稍微修改初始化逻辑即可套用。

今天的每日算法练习就到这里,我们明天再见!👋

相关推荐
朝朝辞暮i17 分钟前
C++ 第 21 课:struct —— 把一组相关数据打包在一起
开发语言·c++·算法
青梅橘子皮23 分钟前
Blue---二分算法(二分查找与二分答案)
算法
长河35 分钟前
Java的GC(垃圾回收)中,标记无用对象的核心方法是可达性分析算法
java·jvm·算法
月光船幽幽1 小时前
加性偏移外推提升参数识别可靠性
python·算法
Ivanqhz2 小时前
层归一化、残差、前馈网络与激活函数简述
服务器·数据库·人工智能·深度学习·算法
不会就选b2 小时前
算法日常・每日刷题--<动态规划>3
数据结构·算法
-dzk-3 小时前
【堆】LC 347.前 K 个高频元素
算法·堆
H.莓飛3 小时前
【数据结构】栈_OJ题
linux·数据结构·算法·centos
Zootopia6263 小时前
多架 eVTOL集群排班调度方案思考
人工智能·算法·数学建模·matlab·动态规划·无人机·evtol
和裕4 小时前
年度框架直供 vs 零散按需采购:定制纸箱采购成本、交付与服务核心区别全对比
大数据·运维·网络·人工智能·算法