题目描述
给你一个 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]
思路
通过顺时针遍历的方式,将结果存储在数组中
-
初始化边界指针:
l(left):左边界,初始为0。r(right):右边界,初始为matrix[0].length - 1。u(up):上边界,初始为0。d(down):下边界,初始为matrix.length - 1。
-
计算总元素数:
k:矩阵中元素的总数,计算为matrix[0].length * matrix.length。用于控制遍历的终止条件,避免多余的遍历。
-
螺旋遍历逻辑:
-
向右遍历上边界:
for (let i = l; i <= r && k--; i++) {
res.push(matrix[u][i]);
}
u++;
从左边界
l到右边界r,将上边界u的所有元素加入结果数组res,然后将上边界下移一行(u++)。 -
向下遍历右边界:
for (let i = u; i <= d && k--; i++) {
res.push(matrix[i][r]);
}
r--;
从上边界
u到下边界d,将右边界r的所有元素加入res,然后将右边界左移一列(r--)。 -
向左遍历下边界:
for (let i = r; i >= l && k--; i--) {
res.push(matrix[d][i]);
}
d--;
从右边界
r到左边界l,将下边界d的所有元素加入res,然后将下边界上移一行(d--)。 -
向上遍历左边界:
for (let i = d; i >= u && k--; i--) {
res.push(matrix[i][l]);
}
l++;
从下边界
d到上边界u,将左边界l的所有元素加入res,然后将左边界右移一列(l++)。
-
-
循环条件:
while (l <= r && u <= d):确保当前的左边界不超过右边界,且上边界不超过下边界。k--:每加入一个元素,k减一。当所有元素都被加入res时,循环终止。
复杂度分析
-
时间复杂度:
O(m * n)m是矩阵的行数,[n](vscode-file://vscode-app/d:/Microsoft VS Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html) 是列数。- 每个元素只被访问一次,整体时间复杂度与矩阵中的元素数量成线性关系。
-
空间复杂度:
O(1)(不计输出数组)- 使用了固定数量的变量来控制遍历(
l,r,u,d,k),不依赖于输入大小。
如果计算输出数组
res,空间复杂度为O(m * n),因为需要存储所有元素 - 使用了固定数量的变量来控制遍历(
code
/**
* @param {number[][]} matrix
* @return {number[]}
*/
var spiralOrder = function (matrix) {
const res = []
let l = 0, r = matrix[0].length - 1, u = 0, d = matrix.length - 1
let k = matrix[0].length * matrix.length
while (l <= r && u <= d) {
for (let i = l; i <= r && k--; i++) {
res.push(matrix[u][i])
}
u++
for (let i = u; i <= d && k--; i++) {
res.push(matrix[i][r])
}
r--
for (let i = r; i >= l && k--; i--) {
res.push(matrix[d][i])
}
d--
for (let i = d; i >= u && k--; i--) {
res.push(matrix[i][l])
}
l++
}
return res
};