54_螺旋矩阵(算法思路,优化及复杂度分析)

73 阅读2分钟

题目描述

给你一个 mn 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。

示例 1:

img

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

示例 2:

img

输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]

思路

通过顺时针遍历的方式,将结果存储在数组中

  1. 初始化边界指针:

    • l(left):左边界,初始为 0
    • r(right):右边界,初始为 matrix[0].length - 1
    • u(up):上边界,初始为 0
    • d(down):下边界,初始为 matrix.length - 1
  2. 计算总元素数:

    • k:矩阵中元素的总数,计算为 matrix[0].length * matrix.length。用于控制遍历的终止条件,避免多余的遍历。
  3. 螺旋遍历逻辑:

    • 向右遍历上边界:

      for (let i = l; i <= r && k--; i++) {

      res.push(matrix[u][i]);

      }

      u++;

      从左边界 l 到右边界 r,将上边界 u 的所有元素加入结果数组 res,然后将上边界下移一行(u++)。

    • 向下遍历右边界:

      for (let i = u; i <= d && k--; i++) {

      res.push(matrix[i][r]);

      }

      r--;

      从上边界 u 到下边界 d,将右边界 r 的所有元素加入 res,然后将右边界左移一列(r--)。

    • 向左遍历下边界:

      for (let i = r; i >= l && k--; i--) {

      res.push(matrix[d][i]);

      }

      d--;

      从右边界 r 到左边界 l,将下边界 d 的所有元素加入 res,然后将下边界上移一行(d--)。

    • 向上遍历左边界:

      for (let i = d; i >= u && k--; i--) {

      res.push(matrix[i][l]);

      }

      l++;

      从下边界 d 到上边界 u,将左边界 l 的所有元素加入 res,然后将左边界右移一列(l++)。

  4. 循环条件:

    • while (l <= r && u <= d):确保当前的左边界不超过右边界,且上边界不超过下边界。
    • k--:每加入一个元素,k 减一。当所有元素都被加入 res 时,循环终止。

复杂度分析

  • 时间复杂度: O(m * n)

    • m 是矩阵的行数,[n](vscode-file://vscode-app/d:/Microsoft VS Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html) 是列数。
    • 每个元素只被访问一次,整体时间复杂度与矩阵中的元素数量成线性关系。
  • 空间复杂度: O(1)(不计输出数组)

    • 使用了固定数量的变量来控制遍历(l, r, u, d, k),不依赖于输入大小。

    如果计算输出数组 res,空间复杂度为 O(m * n),因为需要存储所有元素

code

/**
 * @param {number[][]} matrix
 * @return {number[]}
 */
var spiralOrder = function (matrix) {
    const res = []
    let l = 0, r = matrix[0].length - 1, u = 0, d = matrix.length - 1
    let k = matrix[0].length * matrix.length
    while (l <= r && u <= d) {
        for (let i = l; i <= r && k--; i++) {
            res.push(matrix[u][i])
        }
        u++
        for (let i = u; i <= d && k--; i++) {
            res.push(matrix[i][r])
        }
        r--
        for (let i = r; i >= l && k--; i--) {
            res.push(matrix[d][i])
        }
        d--
        for (let i = d; i >= u && k--; i--) {
            res.push(matrix[i][l])
        }
        l++
    }
    return res
};