LeetCode探索(91):498-对角线遍历

64 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第19天,点击查看活动详情

题目

给你一个大小为 m x n 的矩阵 mat ,请以对角线遍历的顺序,用一个数组返回这个矩阵中的所有元素。

示例 1:

img

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

示例 2:

输入:mat = [[1,2],[3,4]]
输出:[1,2,3,4]

提示:

  • m == mat.length
  • n == mat[i].length
  • 1 <= m, n <= 10^4
  • 1 <= m * n <= 10^4
  • -10^5 <= mat[i][j] <= 10^5

思考

本题难度中等。

首先是读懂题意。给出一个大小为 m x n 的矩阵 mat ,我们需要以对角线遍历的顺序,用一个数组返回这个矩阵中的所有元素。

首先是观察矩阵,一共有 m + n - 1 条对角线。遍历时我们会得到以下规律:

  1. 每一趟对角线中元素的坐标(x, y)相加的和是递增的。第一次遍历和为0,第二次和为1,第三次和为2...
  2. 每次遍历,元素坐标x和y依次递减或递增,幅度为1。
  3. 确定初始值。比如第二趟,2 的坐标(1, 0),4 的坐标(0, 1)。因此 x + y == 1,x 初始值取 1,y 取 0。
  4. 确定结束值。坐标的数值不超过矩阵的大小。

因此,我们可以依据以上规律,转化为代码即可。可以看到我们需要for循环遍历一次所有元素,因此所需的时间复杂度为O(m×n)。

解答

方法一:模拟

/**
 * @param {number[][]} mat
 * @return {number[]}
 */
var findDiagonalOrder = function(mat) {
  let nums = []
  let m = mat.length, n = mat[0].length
  // i 是 x + y 的和
  for (let i = 0; i < m + n; i++) {
    if (i % 2 === 0) { // 第 1 3 5 ... 趟
      // 确定 x y 的初始值
      let x1 = (i < m) ? i : m - 1;
      let y1 = i - x1;
      while (x1 >= 0 && y1 < n) {
        nums.push(mat[x1][y1]);
        x1--;
        y1++;
      }
    } else { // 第 2 4 6 ... 趟
      // 确定 x y 的初始值
      let y2 = (i < n) ? i : n - 1;
      let x2 = i - y2;
      while (y2 >= 0 && x2 < m) {
        nums.push(mat[x2][y2]);
        x2++;
        y2--;
      }
    }
  }
  return nums
}

// 执行用时:76 ms, 在所有 JavaScript 提交中击败了96.03%的用户
// 内存消耗:47.2 MB, 在所有 JavaScript 提交中击败了52.24%的用户
// 通过测试用例:32 / 32

复杂度分析:

  • 时间复杂度:O(m×n),其中 m 为矩阵行的数量,n 为矩阵列的数量。需要遍历一遍矩阵中的所有元素。
  • 空间复杂度:O(1)。除返回值外不需要额外的空间。

参考