螺旋矩阵
问题
给你一个 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
答案
方法一:边界收缩(推荐)
核心思路:定义四个边界 top、bottom、left、right,每走完一条边就收缩对应的边界。
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]
复杂度分析
- 时间复杂度: — 每个元素访问一次
- 空间复杂度: — 不算输出
常见错误
最后两步(向左、向上)需要额外检查边界。否则在非正方形矩阵或只剩一行/一列时会重复遍历。
方法二:方向数组模拟
使用方向数组,碰到边界或已访问元素就转向:
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 到 n² 的螺旋矩阵:
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: 螺旋矩阵在前端有什么应用?
答案:
- 矩阵动画:元素按螺旋顺序依次出现
- 九宫格抽奖:按螺旋顺序转动
- 图片拼图:按螺旋顺序拼合