题目
给你一个 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
思路
- 本题的解法有多种,这里介绍一种比较简单的解法。 我们可以按照顺时针的方向依次遍历矩阵的每一个元素,并将其添加到结果数组中。具体来说,假设当前要遍历的区域左上角的坐标为 (top, left),右下角的坐标为 (bottom, right),则按照如下步骤遍历:
- 从左到右遍历上侧元素,依次将其添加到结果数组中;
- 从上到下遍历右侧元素,依次将其添加到结果数组中;
- 如果 left < right 且 top < bottom,则从右到左遍历下侧元素,依次将其添加到结果数组中;
- 如果 left < right 且 top < bottom,则从下到上遍历左侧元素,依次将其添加到结果数组中;
- 将 left 和 top 分别加上 1,将 right 和 bottom 分别减去 1,然后回到步骤 1。 注意:在第 3 步和第 4 步中,需要判断 left < right 且 top < bottom,这是为了避免遍历到已经遍历过的元素。 最后,当 left == right 且 top == bottom 时,说明只剩下一个元素没有遍历,将其添加到结果数组中即可。
function spiralOrder(matrix: number[][]): number[] {
const result = [];
// 异常处理
if(!matrix || !matrix.length || !matrix[0].length) return result
// 记录,行索引范围:上-下,列索引范围:左-右
let top = 0;
let bottom = matrix.length - 1;
let left = 0;
let right = matrix[0].length - 1;
// 顺时针遍历
while(left <= right && top <= bottom) {
// 上:从左到右
for(let i = left; i <= right; i++) {
result.push(matrix[top][i]);
}
top++;// 注意这里top要下移一行
// 右:从上到下。
for(let i = top; i <= bottom; i++) {
result.push(matrix[i][right]);
}
right--;// 注意这里right要左移一列
if(left <= right && top <= bottom) {// top,left有变动,所以需要重新判断下
// 下:从右到左。
for(let i = right; i >= left; i--) {
result.push(matrix[bottom][i]);
}
bottom--;// 注意这里bottom要上移一行
// 左:从下到上。
for(let i = bottom; i >= top; i--) {
result.push(matrix[i][left]);
}
left++;// 注意这里left要右移一行
}
}
return result;
};
总结
- 时间复杂度:,其中 和 分别是矩阵的行数和列数。
- 空间复杂度:。
除了上述的解法,还有以下两种常见的解法:
-
解法一:模拟旋转矩阵 这种解法的思路是将矩阵逆时针旋转90度,然后按照从左到右、从上到下的顺序遍历矩阵,并将遍历到的元素添加到结果数组中。具体来说,我们可以先将矩阵逆时针旋转90度,然后按照行的顺序遍历矩阵,并将遍历到的元素添加到结果数组中。时间复杂度为 ,空间复杂度为 。
-
解法二:按层遍历 这种解法的思路是按照从外到内的顺序遍历矩阵,并将遍历到的元素添加到结果数组中。具体来说,我们可以定义一个变量 表示当前要遍历的层数,从外层开始依次往里面遍历。对于每一层,我们可以将其分为四个边,从左到右、从上到下依次遍历,将遍历到的元素添加到结果数组中。时间复杂度为 ,空间复杂度为 。
-
综上所述,这道题目有多种解法,每种解法都有其优点和局限性,具体选择哪种解法需要根据实际情况进行选择。