54. 螺旋矩阵(JavaScript)
给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。
示例 1:
输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,3,6,9,8,7,4,5]
示例 2:
输入:
[
[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,代表相同位置上的原矩阵元素未被访问,0代表已被访问。
设置方向变量direction,0、1、2、3分别代表右、下、左、上四个方向。
设置结果数组result = [ ].
遍历标志矩阵:当前tag位存在且为1时,将此元素加入结果数组,并将tag为置为0,并判断此时的方向:
1、方向为0(右),若右边的元素不存在,或已被访问,则改变方向为1(下),否则继续向右移动一格
2、方向为1(下),若下边的元素不存在,或已被访问,则改变方向为2(左),否则继续向下移动
3、方向为2(左),若左边的元素不存在,或已被访问,则改变方向为3(上),否则继续向左移动
4、方向为3(上),若上边的元素不存在,或已被访问,则改变方向为0(右),否则继续向上移动
/**
* @param {number[][]} matrix
* @return {number[]}
*/
var spiralOrder = function(matrix) {
if (matrix.length === 0) return []
let tag = [],
row = matrix.length,
col = matrix[0].length,
direction = 0, // 0右,1下,2左,3上
result = []
for (let i = 0; i < row; i++) {
tag[i] = [];
for (let j = 0; j < col; j++) {
tag[i][j] = 1; // 1:未访问,0:已访问
}
}
let r = 0,
c = 0;
while(tag[r] && tag[r][c] === 1) {
result.push(matrix[r][c])
tag[r][c] = 0
switch(direction) {
case 0:
if (!tag[r][c+1]) {
direction = 1
r++
} else { c++ }
break
case 1:
if (tag[r+1] && tag[r+1][c]) {
r++
} else {
direction = 2
c--
}
break
case 2:
if (!tag[r][c-1]) {
direction = 3
r--
} else { c-- }
break
case 3:
if (!tag[r-1][c]) {
direction = 0
c++
} else { r-- }
break
}
}
return result;
};
方法二:
设置四个端点——上下左右:top、bottom、left、right
当上小于等于下、左小于等于右时循环:
1、向右移动,从left到right这一行元素加入结果数组result,之后将top++,(因为最上面一行都计入了,所以top要加1)并判断此时top与bottom是否合理
2、向下移动,从top到bottom这一列元素加入result,之后将right--,并判断right是否大于l等于eft
3、向左移动,加入从right到left这一行元素,之后将bottom--,同样判断bottom是否还大于等于top
4、向上移动,加入从bottom到top这一列元素,之后将left++,同样判断left是否还小于等于right
循环中任何时候只要top大于了bottom或者left大于了right,就要跳出循环。
/**
* @param {number[][]} matrix
* @return {number[]}
*/
var spiralOrder = function(matrix) {
if (matrix.length === 0) return []
let top = 0,
bottom = matrix.length - 1,
left = 0,
right = matrix[0].length - 1,
result = [];
while (top <= bottom && left <= right) {
for (let j = left; j <= right; j ++) {
result.push(matrix[top][j])
}
if (++top > bottom) break
for (let i = top; i <= bottom; i++) {
result.push(matrix[i][right])
}
if (--right < left) break
for (let j = right; j >= left; j--) {
result.push(matrix[bottom][j])
}
if (--bottom < top) break
for (let i = bottom; i >= top; i--) {
result.push(matrix[i][left])
}
if (++left > right) break
}
return result
};