算法题-数组-59-螺旋矩阵 II

56 阅读1分钟

59-螺旋矩阵 II

题目描述

给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。

示例 1:

image.png

输入: n = 3
输出: [[1,2,3],[8,9,4],[7,6,5]]

示例 2:

输入: n = 1
输出: [[1]]

分析

先初始化n*n的数组,所有的值都为0

然后遍历从1到n*n,定义一个前进方向,右下左上依次切换,切换的条件是如果按照当前方向前进的话,下一个值为undefined或者不为0的时候,则换成下一个方向。

题解

/**
 * @param {number[][]} matrix
 * @return {number[]}
 */
var spiralOrder = function(matrix) {
  let res = [];
  let exists = [];

  let m = matrix.length;
  let n = matrix[0].length;

  let x=y=0;
  let index = 0; // 当前方向
  let chioces = [
    [1, 0], // 向右
    [0, 1], // 向下
    [-1, 0], // 向左
    [0, -1], // 向上
  ]
  for(let cnt=1; cnt<m*n+1; cnt++) {
    exists.push(y*n+x);
    res.push(matrix[y][x])
    let newy = y+chioces[index][1]
    let newx = x+chioces[index][0]
    if(matrix[newy]==undefined || matrix[newy][newx]==undefined || exists.includes(newy*n+newx)) {
      index = (index + 1) % 4
    }
    y = y+chioces[index][1]
    x = x+chioces[index][0]
  }
  return res
};

分析

时间复杂度:O(n^2)

空间复杂度:O(1)

优化 - 代码可读性

之前用的方法是 模拟,优化方法是 按层模拟。相当于是不断更新边界条件。

  1. 从左到右填入上侧元素,依次为 (top,left) 到 (top,right)。
  2. 从上到下填入右侧元素,依次为 (top+1,right) 到 (bottom,right)。
  3. 如果 left<right 且 top<bottom,则从右到左填入下侧元素,依次为 (bottom,right−1) 到 (bottom,left+1),以及从下到上填入左侧元素,依次为 (bottom,left) 到 (top+1,left)。

填完当前层的元素之后,将 left 和 top 分别增加 1,将 right 和 bottom 分别减少 1,进入下一层继续填入元素,直到填完所有元素为止。

/**
 * @param {number} n
 * @return {number[][]}
 */
var generateMatrix = function(n) {
    let startX = startY = 0;   // 起始位置
    let loop = Math.floor(n/2);   // 旋转圈数
    let mid = Math.floor(n/2);    // 中间位置
    let offset = 1;    // 控制每一层填充元素个数
    let count = 1;     // 更新填充数字
    let res = new Array(n).fill(0).map(() => new Array(n).fill(0));

    while (loop--) {
        let row = startX, col = startY;
        // 上行从左到右(左闭右开)
        for (col = startY; col < n - offset; col++) {
            res[row][col] = count++;
        }
        // 右列从上到下(左闭右开)
        for (row=startX; row <n - offset; row++) {
            res[row][col] = count++;
        }
        // 下行从右到左(左闭右开)
        for (; col > startY; col--) {
            res[row][col] = count++;
        }
        // 左列做下到上(左闭右开)
        for (; row > startX; row--) {
            res[row][col] = count++;
        }

        // 更新起始位置
        startX++;
        startY++;

        // 更新offset
        offset ++;
    }
    // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
    if (n % 2 === 1) {
        res[mid][mid] = count;
    }
    return res;
};

难点

模拟、螺旋打印