// 封装顺时针遍历二维数组函数
function spiralOrder (matrix) {
// 计算矩阵的行数和列数
const rows = matrix.length;
const cols = matrix[0].length;
// 定义四个变量,分别表示上下左右四个边界位置
let top = 0,
bottom = rows - 1,
left = 0,
right = cols - 1;
// 定义一个新数组用于存储顺时针遍历结果
const result = [];
// 当左边界小于等于右边界且上边界小于等于下边界时,继续循环
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;
}
// 封装打印一维数组函数
function printArray (arr) {
console.log(`[${arr.join(', ')}]`);
}
// 示例代码
const matrix = [
[1, 2, 3, 4, 5, 6, 7],
[1, 2, 3, 4, 5, 6, 7],
[1, 2, 3, 4, 5, 6, 7],
[1, 2, 3, 4, 5, 6, 7],
[1, 2, 3, 4, 5, 6, 7],
[1, 2, 3, 4, 5, 6, 7],
[1, 2, 3, 4, 5, 6, 7],
];
const result = spiralOrder(matrix);
printArray(result); // [1, 2, 3, 6, 9, 8, 7, 4, 5]
在遍历二维数组时,我们需要使用四个变量 top
、bottom
、left
和 right
来表示当前遍历的子矩阵的上下左右边界。在顺时针遍历时,我们需要依次遍历这些边界上的元素,并且每次遍历完一条边界上的元素后,都要将该边界向内收缩一格。
具体来说,我们首先从最外层的上边界开始遍历,遍历完该边界上的所有元素后,将上边界向下移动一格,使得接下来的循环可以遍历更内层的矩阵。类似地,当遍历完右边界上的元素后,我们将右边界向左收缩一格,以便可以遍历接下来的底部行。当我们完成底部行的遍历时,将底部边界向上收缩一格,以便可以遍历左侧列。当我们完成左侧列的遍历时,将左侧边界向右扩展一格,以便可以遍历接下来的顶部行。
因此,在每次遍历完一条边界上的元素后,我们需要将该边界向内收缩一格,以便可以遍历接下来的元素,这就是为什么 bottom
和 right
需要减去 1
的原因。而由于顺时针遍历的方向是从左到右、从上到下,因此在每次遍历完一行或一列后,我们需要将对应的边界向内收缩一格,以便可以遍历下一行或下一列。因此 top
和 left
不需要减去 1
。