题目
// 这里用集合方式来表示
{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
}
打印输出:1, 2, 3, 6, 9, 8, 7, 4, 5
基本分析
先对算法进行归类,这里暂时先归:线性查找,所以会有基础循环结构。
然后确定需要几层循环:索引、边界、循环次数。
1. 索引
每一轮遍历到的 index 范围
2. 边界
x, y 轴两个方向的最大值
边界是一个收窄的控制,遍历是按圈进行控制外层循环,内层各循环只需要在边界 Range 进行打印。
外层循环变量:loop
内层循环变量:index
# 打印策略
1. 默认就开始左到右的打印
2. 左到右打印完成后,进行上到下打印,没有到最后一列 loop < endY,均可进行上到下的打印
3. 上到下打印完成后,进行右到左打印,只要 loop < endX 和 loop < endY 区间内就可以打印
4. 右到左打印完成后,进行下到上打印,只要在 loop < endX 和 loop < endY - 1 区间内就可以打印
5. 然后进行下一圈的打印,回到 `步骤1` 重新执行
3. 循环次数
- 外层循环
由于每一圈都是要打印 2 次,所以整体 loop * 2 < length 就是打印的外层最大循环次数;
loopCount * 2 < xLen && loopCount * 2 < yLen
- 内层循环
主要需要注意不变的是哪一个元素,分别从:左、右、下、上方向进行推导,可以进行 a[i][j] 先模拟,使用以前高中解基本数列的模式:
0: { a[0][0], a[0][1], a[0][2] }
1: { a[1][0], a[1][1], a[1][2] }
2: { a[2][0], a[2][1], a[2][2] }
- 左到右:
matrix[不变][i] - 上到下:
matrix[i][不变] - 右到左:
matrix[不变][i] - 下到上:
matrix[i][不变]
4. 实现
function print(matrix) {
if (matrix?.length <= 0) {
return [];
}
const yLen = matrix.length;
const xLen = matrix[0].length;
let loop = 0;
const result = [];
// 外层循环:循环最大边界
while (loop * 2 < xLen && loop * 2 < yLen) {
// 行遍历的边界, 遍历一圈,就会缩小矩形边界(螺旋打印)
const endX = xLen - 1 - loop;
const endY = yLen - 1 - loop;
// 遍历 x 轴 👉
for (let i = loop; i <= endX; i++) {
// 外层索引不变
result.push(matrix[loop][i]);
}
// 遍历 y 轴 👇
if (loop < endY) {
for (let i = loop + 1; i <= endY; i++) {
// 内层索引不变
result.push(matrix[i][endX]);
}
}
// 遍历 x 轴 👈
if (loop < endX && loop < endY) {
for (let i = endX - 1; i >= loop; i--) {
// 外层索引不变
result.push(matrix[endY][i]);
}
}
// 遍历 y 轴 👆
if (loop < endX && loop < endY - 1) {
for (let i = endY - 1; i >= loop + 1; i--) {
// 内层索引不变
result.push(matrix[i][loop]);
}
}
loop++;
}
return result;
}