刷 easy 算法记录 - 矩阵顺时针打印

166 阅读1分钟

题目

// 这里用集合方式来表示
{
  {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;
}