「前端刷题」54. 螺旋矩阵

538 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

题目

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

 

示例 1:

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

示例 2:

**输入:**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]

 

提示:

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 10
  • -100 <= matrix[i][j] <= 100

解题思路

思路1

  1. 首先要判断空数组,返回[]
  2. 无限循环,访问四条边,若越界,则说明访问完了,退出
const spiralOrder = matrix => {
    const res = [];

    // 定义行、列
    // 可能是空数组,所以加一个'?'
    const [m, n] = [matrix.length, matrix[0]?.length];
    if (!m || !n) return res;

    // 初始化:左、右、上、下
    let [left, right, up, down] = [0, n - 1, 0, m - 1];

    while (1) {
        // 访问上边,从左到右,访问完毕后,up++
        for (let j = left; j <= right; j++) res.push(matrix[up][j]);
        up++;
        // 若up比down大,说明都访问完了,退出
        if (up > down) break;

        // 以下同理
        for (let i = up; i <= down; i++) res.push(matrix[i][right]);
        right--;
        if (right < left) break;

        for (let j = right; j >= left; j--) res.push(matrix[down][j]);
        down--;
        if (down < up) break;

        for (let i = down; i >= up; i--) res.push(matrix[i][left]);
        left++;
        if (left > right) break;
    }

    return res;
};

常规法

 var spiralOrder = function (arr) {
  // 方向默认右边
  let dir = 'right';
  // m 行 n 列
  let m = arr.length, n = arr[0].length;
  let y = 0, x = 0, r = [];
  // 缓存结果
  let map = {};
  while (true) {
    let key = `${y},${x}`;
    r.push(arr[y][x]);
    map[key] = 1;
    const canRight = x < n - 1 && !map[`${y},${x + 1}`];
    const canDown = (y < m - 1) && !map[`${y + 1},${x}`];
    const canLeft = x > 0 && !map[`${y},${x - 1}`];
    const canTop = y > 0 && !map[`${y - 1},${x}`];

    if (dir === 'right') {
      if (canRight) {
        x++
        continue
      }
      if (canDown) {
        dir = 'bottom';
        y++;
        continue
      }
      // 无路可走,退出
      break;
    }

    if (dir === 'bottom') {
      if (canDown) {
        y++;
        continue
      }
      if (canLeft) {
        dir = 'left';
        x--;
        continue;
      }
      // 无路可走,退出
      break;
    }

    if (dir === 'left') {
      if (canLeft) {
        x--;
        continue;
      }
      if (canTop) {
        y--;
        dir = 'top';
        continue;
      }
      // 无路可走,退出
      break;
    }

    if (dir === 'top') {
      if (canTop) {
        y--;
        continue;
      }
      if (canRight) {
        x++;
        dir = 'right';
        continue;
      }
      // 无路可走,退出
      break;
    }
  };
  return r;
}