JS螺旋矩阵II

119 阅读2分钟

🌱题目

力扣题目链接

🌱思路

这道题需要坚持循环不变量的原则,我们可以模拟顺时针画矩阵的过程:

  • 填充上行从左到右
  • 填充右列从上到下
  • 填充下行从右到左
  • 填充左列从下到上

在我们画的过程中,会发现这里的边界条件很多,很容易一进循环深似海,所以这里可以使用左闭右开的原则,如下图:

实现思路

  1. 坚持循环不变量的原则,边界区间左闭右开

  2. 用while生成螺旋矩阵

    1. 首先从左到右填充上边界。
    2. 然后从上到下填充右边界。
    3. 接着从右到左填充下边界。
    4. 最后从下到上填充左边界。
  3. 循环完后更新起始位置和偏移量,为生成下一层做准备。

  4. 如果是n是奇数的话,就需要单独处理中间位置。

  • 时间复杂度 O(n^2): 模拟遍历二维矩阵的时间
  • 空间复杂度 O(1)
/**
 * 生成 n x n 的螺旋矩阵
 *
 * 1.坚持循环不变量原则,边界区间左闭右开
 * 2.while循环生成螺旋矩阵,就是二维矩阵(从左到右,从上到下,从右到左,从下到上)
 * 3.如果n是奇数的话,则需要单独处理中间的值
 */
function generateMatrix(n) {
  // 生成二维矩阵
  let arr = new Array(n).fill(0).map(() => new Array(n).fill(0));
  // 定义原点startX,startY
  let startX = 0,
    startY = 0;
  // 计算要转多少圈和中间的位置
  let loop = Math.floor(n / 2);
  let mid = Math.floor(n / 2);
  // 控制每一层填充的元素
  let offset = 1;
  // 填充的值
  let count = 1;
  // while循环 要确定循环多少圈
  while (loop--) {
    // 定义行和列的初始索引
    let rowIndex = startX,
      colIndex = startY;
    // 从左到右
    for (; colIndex < n - offset; colIndex++) {
      arr[rowIndex][colIndex] = count++;
    }
    // 从上到下
    for (; rowIndex < n - offset; rowIndex++) {
      arr[rowIndex][colIndex] = count++;
    }
    // 从右到左
    for (; colIndex > startY; colIndex--) {
      arr[rowIndex][colIndex] = count++;
    }
    // 从下到上
    for (; rowIndex > startX; rowIndex--) {
      arr[rowIndex][colIndex] = count++;
    }
    // 判断是否有中间值,也就是n是否为奇数
    if (n % 2 !== 0) {
      arr[mid][mid] = count;
    }
    // 更新offset和初始位置
    offset++;
    startX++;
    startY++;
  }
  return arr;
}
const res = generateMatrix(5);
console.log(res);

🍀类似题目

🍀总结

该题目是通过模拟螺旋填充的过程,生成一个 n x n 的螺旋矩阵。首先初始化变量和二维零矩阵,然后按照从左到右、从上到下、从右到左、从下到上的顺序填充矩阵,最后处理矩阵大小为奇数时的特殊情况,返回生成的螺旋矩阵。

这道面试题算是高频出现的题目之一,它并不要求掌握复杂的算法,而是侧重于模拟某个过程,但非常考验我们对代码的驾驭和把握能力。