中等 | 模拟 |
一. 题目描述
给你一个 **m**
行 **n**
列的矩阵 **matrix**
,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
二. 题目示例
:::tips
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
:::
:::tips
输入: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]
:::
三. 题目解答
1. 思路
按照模拟的思路,分别进行上右下左的遍历,即一圈的遍历。圈结束后,会剩下一行或一列或一项,再判断进行遍历。
- 圈的遍历
- 如果一条边从头遍历到底,则下一条边遍历的起点随之变化
- 选择不遍历到底,可以减小横向、竖向遍历之间的影响
- 一轮迭代结束时,4条边的两端同时收窄 1
- 一轮迭代所做的事情变得很清晰:遍历一个“圈”,遍历的范围收缩为内圈
- 一层层向里处理,按顺时针依次遍历:上、右、下、左。
- 不再形成“环”了,就会剩下:一行或一列,然后单独判断
- 四个边界
- 上边界
**top**
:**0**
- 下边界
**bottom**
:**matrix.length - 1**
- 左边界
**left**
:**0**
- 右边界
**right**
:**matrix[0].length - 1**
- 上边界
- 循环条件
- 矩阵不一定是方阵,
**top < bottom && left < right**
是循环的条件 - 无法构成“环”了,就退出循环,退出时可能是这 3 种情况之一:
**top == bottom && left < right**
—— 剩一行**top < bottom && left == right**
—— 剩一列**top == bottom && left == right**
—— 剩一项(也算 一行/列)
- 矩阵不一定是方阵,
- 处理剩下的单行或单列
- @param {number[][]} matrix
- @return {number[]}
/
var spiralOrder = function(matrix) {
let result = [];
const m = matrix.length;
const n = matrix[0].length;
let top = 0, bottom = m-1; // [i][]
let left = 0, right = n-1; // [*][j]
while(top < bottom && left < right){
// 有头没尾循环
// 上
for(let j=left; j<right; j++){
} // 右 for(let i=top; i<bottom; i++){result.push(matrix[top][j]);
} // 下 for(let j=right; j>left; j—){result.push(matrix[i][right]);
} // 左 for(let i=bottom; i>top; i—){result.push(matrix[bottom][j]);
} top++; right—; left++; bottom—; } // 剩余一行: 上 if(top == bottom){ for(let j=left; j<=right; j++){result.push(matrix[i][left]);
} } else if(left == right){ // 剩余一列 || 剩余一个: 右 for(let i=top; i<=bottom; i++){result.push(matrix[top][j]);
} } return result; }; ```result.push(matrix[i][right]);