跳到主要内容

螺旋矩阵

问题

给你一个 m x n 的矩阵 matrix,请按照顺时针螺旋顺序返回矩阵中的所有元素。

示例:

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

1 → 2 → 3

4 → 5 6
↑ ↓
7 ← 8 ← 9

来源:LeetCode 54. 螺旋矩阵

答案

方法一:边界收缩(推荐)

核心思路:定义四个边界 topbottomleftright,每走完一条边就收缩对应的边界。

spiralOrder.ts
function spiralOrder(matrix: number[][]): number[] {
if (matrix.length === 0) return [];

const result: number[] = [];
let top = 0;
let bottom = matrix.length - 1;
let left = 0;
let right = matrix[0].length - 1;

while (top <= bottom && left <= right) {
// → 向右遍历顶行
for (let col = left; col <= right; col++) {
result.push(matrix[top][col]);
}
top++;

// ↓ 向下遍历右列
for (let row = top; row <= bottom; row++) {
result.push(matrix[row][right]);
}
right--;

// ← 向左遍历底行(注意检查 top <= bottom)
if (top <= bottom) {
for (let col = right; col >= left; col--) {
result.push(matrix[bottom][col]);
}
bottom--;
}

// ↑ 向上遍历左列(注意检查 left <= right)
if (left <= right) {
for (let row = bottom; row >= top; row--) {
result.push(matrix[row][left]);
}
left++;
}
}

return result;
}

图解过程(3×3 矩阵)

初始:top=0, bottom=2, left=0, right=2

Round 1:
→ 顶行: [1, 2, 3], top=1
↓ 右列: [6, 9], right=1
← 底行: [8, 7], bottom=1
↑ 左列: [4], left=1

Round 2:
→ 顶行: [5], top=2
top > bottom → 结束

结果:[1, 2, 3, 6, 9, 8, 7, 4, 5]
复杂度分析
  • 时间复杂度O(m×n)O(m \times n) — 每个元素访问一次
  • 空间复杂度O(1)O(1) — 不算输出
常见错误

最后两步(向左、向上)需要额外检查边界。否则在非正方形矩阵或只剩一行/一列时会重复遍历。


方法二:方向数组模拟

使用方向数组,碰到边界或已访问元素就转向:

spiralOrderDirection.ts
function spiralOrder(matrix: number[][]): number[] {
const m = matrix.length;
const n = matrix[0].length;
const result: number[] = [];
const visited = Array.from({ length: m }, () => new Array(n).fill(false));

// 方向:右、下、左、上
const dirs = [[0, 1], [1, 0], [0, -1], [-1, 0]];
let dirIndex = 0;
let row = 0, col = 0;

for (let i = 0; i < m * n; i++) {
result.push(matrix[row][col]);
visited[row][col] = true;

// 计算下一个位置
const nextRow = row + dirs[dirIndex][0];
const nextCol = col + dirs[dirIndex][1];

// 如果越界或已访问,转向
if (
nextRow < 0 || nextRow >= m ||
nextCol < 0 || nextCol >= n ||
visited[nextRow][nextCol]
) {
dirIndex = (dirIndex + 1) % 4; // 顺时针转向
}

row += dirs[dirIndex][0];
col += dirs[dirIndex][1];
}

return result;
}

常见面试追问

Q1: 如何生成螺旋矩阵?(LeetCode 59)

答案:给定 n,生成 1 的螺旋矩阵:

function generateMatrix(n: number): number[][] {
const matrix = Array.from({ length: n }, () => new Array(n).fill(0));
let top = 0, bottom = n - 1, left = 0, right = n - 1;
let num = 1;

while (top <= bottom && left <= right) {
for (let col = left; col <= right; col++) matrix[top][col] = num++;
top++;
for (let row = top; row <= bottom; row++) matrix[row][right] = num++;
right--;
for (let col = right; col >= left; col--) matrix[bottom][col] = num++;
bottom--;
for (let row = bottom; row >= top; row--) matrix[row][left] = num++;
left++;
}

return matrix;
}

Q2: 如何旋转矩阵 90 度?(LeetCode 48)

答案:先转置,再左右翻转:

function rotate(matrix: number[][]): void {
const n = matrix.length;

// 转置
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
[matrix[i][j], matrix[j][i]] = [matrix[j][i], matrix[i][j]];
}
}

// 左右翻转
for (let i = 0; i < n; i++) {
matrix[i].reverse();
}
}

Q3: 螺旋矩阵在前端有什么应用?

答案

  • 矩阵动画:元素按螺旋顺序依次出现
  • 九宫格抽奖:按螺旋顺序转动
  • 图片拼图:按螺旋顺序拼合

相关链接