Skip to content

螺旋矩阵

LeetCode 官方题目链接

1. 题目呈现

难度等级:🟡 中等
核心考察点:矩阵、模拟

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


2. 解题思路拆解

方法:模拟层层遍历

这道题没有太复杂的算法思想,核心在于模拟螺旋移动的过程,并精确控制边界。

  1. 定义边界

    • 我们需要四个变量来表示当前的边界:top, bottom, left, right
    • 初始时:top = 0, bottom = m-1, left = 0, right = n-1
  2. 模拟过程

    • 只要 left <= righttop <= bottom,就继续循环。
    • 向右移动:从 leftright 遍历 top 行。遍历完,top++
    • 向下移动:从 topbottom 遍历 right 列。遍历完,right--
    • 向左移动:需要先检查 top <= bottom(防止重复遍历)。从 rightleft 遍历 bottom 行。遍历完,bottom--
    • 向上移动:需要先检查 left <= right(防止重复遍历)。从 bottomtop 遍历 left 列。遍历完,left++
  3. 终止条件

    • 当边界交错时(left > righttop > bottom),循环结束。

3. 代码实现

javascript
/**
 * @param {number[][]} matrix
 * @return {number[]}
 */
var spiralOrder = function(matrix) {
    if (!matrix.length || !matrix[0].length) {
        return [];
    }
    
    const result = [];
    let top = 0;
    let bottom = matrix.length - 1;
    let left = 0;
    let right = matrix[0].length - 1;
    
    while (top <= bottom && left <= right) {
        // 1. 向右移动
        for (let i = left; i <= right; i++) {
            result.push(matrix[top][i]);
        }
        top++; // 上边界下移
        
        // 2. 向下移动
        for (let i = top; i <= bottom; i++) {
            result.push(matrix[i][right]);
        }
        right--; // 右边界左移
        
        // 3. 向左移动
        // 注意:需要检查 top <= bottom,因为 top 刚刚变了
        if (top <= bottom) {
            for (let i = right; i >= left; i--) {
                result.push(matrix[bottom][i]);
            }
            bottom--; // 下边界上移
        }
        
        // 4. 向上移动
        // 注意:需要检查 left <= right,因为 right 刚刚变了
        if (left <= right) {
            for (let i = bottom; i >= top; i--) {
                result.push(matrix[i][left]);
            }
            left++; // 左边界右移
        }
    }
    
    return result;
};

代码执行演示

输入 matrix = [[1,2,3],[4,5,6],[7,8,9]]

  • 初始:top=0, bottom=2, left=0, right=2
  • 第 1 轮循环
    • 向右:遍历 row 0, col 0->2res=[1,2,3]top 变为 1。
    • 向下:遍历 col 2, row 1->2res=[1,2,3,6,9]right 变为 1。
    • 检查top(1) <= bottom(2),通过。
    • 向左:遍历 row 2, col 1->0res=[1,2,3,6,9,8,7]bottom 变为 1。
    • 检查left(0) <= right(1),通过。
    • 向上:遍历 col 0, row 1->1res=[1,2,3,6,9,8,7,4]left 变为 1。
  • 第 2 轮循环
    • 当前:top=1, bottom=1, left=1, right=1。满足条件。
    • 向右:遍历 row 1, col 1->1res=[..., 5]top 变为 2。
    • 向下:遍历 col 1, row 2->1 (不执行)。right 变为 0。
    • 检查top(2) <= bottom(1)不通过。跳过向左。
    • 检查left(1) <= right(0)不通过。跳过向上。
  • 循环结束。返回 [1,2,3,6,9,8,7,4,5]

4. 复杂度分析

维度描述
时间复杂度$O(mn)$。我们需要遍历矩阵中的每个元素一次。
空间复杂度$O(1)$。除了输出数组外,只需要常数空间存储边界变量。

Power by VitePress