0054.螺旋矩阵
难度:🟡 中等
标签:数组
、矩阵
、模拟
链接: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]
解题思路
核心思想
本题的核心是模拟螺旋遍历矩阵的过程。我们可以把矩阵看作由多个“矩形框”嵌套而成,我们的任务就是一层一层地从外到内打印这些“矩形框”。
思路选择
按层模拟法 是解决此问题的最直观、最清晰的思路。
我们定义四个变量
top
,bottom
,left
,right
来表示当前需要遍历的“矩形框”的四个边界。在一个循环中,我们依次完成“从左到右”、“从上到下”、“从右到左”、“从下到上”四个步骤的遍历,每完成一步,就将对应的边界向内收缩。
循环的条件是上边界不大于下边界,且左边界不大于右边界。
关键步骤
处理边界情况:如果矩阵为空,直接返回空数组。
初始化边界:初始化四个边界变量:
top = 0
,bottom = matrix.length - 1
,left = 0
,right = matrix[0].length - 1
。循环遍历:当
left <= right
且top <= bottom
时,持续循环。 a. 从左到右 (上边界): 遍历matrix[top]
从left
到right
的所有元素,然后top++
。 b. 从上到下 (右边界): 遍历matrix
从top
到bottom
的right
列元素,然后right--
。 c. 从右到左 (下边界): 检查top <= bottom
是否仍然成立(防止单行矩阵重复遍历)。如果成立,遍历matrix[bottom]
从right
到left
的所有元素,然后bottom--
。 d. 从下到上 (左边界): 检查left <= right
是否仍然成立(防止单列矩阵重复遍历)。如果成立,遍历matrix
从bottom
到top
的left
列元素,然后left++
。返回结果:循环结束后,所有元素都已按螺旋顺序存入结果数组,返回即可。
代码实现
/**
* @param {number[][]} matrix
* @return {number[]}
*/
var spiralOrder = function (matrix) {
if (!matrix.length || !matrix[0].length) {
return [];
}
const result = [];
let top = 0, bottom = matrix.length - 1, left = 0, right = matrix[0].length - 1;
while (left <= right && top <= bottom) {
// 从左到右
for (let i = left; i <= right; i++) {
result.push(matrix[top][i]);
}
top++;
// 从上到下
for (let i = top; i <= bottom; i++) {
result.push(matrix[i][right]);
}
right--;
// 检查边界,防止重复
if (top <= bottom) {
// 从右到左
for (let i = right; i >= left; i--) {
result.push(matrix[bottom][i]);
}
bottom--;
}
// 检查边界,防止重复
if (left <= right) {
// 从下到上
for (let i = bottom; i >= top; i--) {
result.push(matrix[i][left]);
}
left++;
}
}
return result;
};
复杂度分析
时间复杂度:O(m × n) 其中 m 和 n 分别是矩阵的行数和列数。每个元素都会被访问且仅被访问一次。
空间复杂度:O(1) 不考虑存储返回结果的数组,我们只使用了常数个额外变量作为边界指针,空间消耗是恒定的。
相关题目
总结
本题是矩阵遍历的经典问题,主要考察对循环边界条件的细致处理能力。通过“按层模拟”并不断收缩边界的方法,可以清晰地、有条不紊地解决问题。在处理“从右到左”和“从下到上”的步骤时,需要额外进行边界检查,以防止在只有一行或一列的瘦长矩阵中出现重复遍历。