【我也想刷穿 LeetCode啊】498. 对角线遍历

146 阅读1分钟

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

现在前端很多岗位面试需要有一定的算法基础,或者说经常刷算法的会优先考虑。

因此每天刷刷LeetCode非常有必要

在这之前我也刷过一些算法题,也希望以后也坚持刷,跟某掘友一样,我也想刷穿 LeetCode

一、题目描述

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

 

示例 1:

输入: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 <= 104 1 <= m * n <= 104 -105 <= mat[i][j] <= 105

来源:力扣(LeetCode) 链接:leetcode.cn/problems/di… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

二、思路分析

1.首先遍历矩阵,然后新建一个map来存储key和value,key为横纵坐标之和,value为key相等的元素数组(即每条对角线的元素组成的数组)

2.然后新建一个结果数组res,遍历map,将对角线是偶数(即第2条对角线、第4条对角线..,满足key % 2 === 1)的元素正序放入res中,将对角线是奇数(即第1条对角线、第3条对角线..,满足key % 2 === 0)的元素倒序放入res中,最后返回res即可

三、代码实现

/**
 * @param {number[][]} mat
 * @return {number[]}
 */
var findDiagonalOrder = function(mat) {
    const row = mat.length
    const col = mat[0].length
    const record = new Map()
    for (let i = 0; i < row; i++) {
        for (let j = 0; j < col; j++) {
            const key = i + j
            if (!record.has(key)) record.set(key, [])
                record.get(key).push(mat[i][j])
            }
        }
    const res = []
    for (const [key, nums] of record.entries()) {// entries()获取所有的键值对数组:[[key1, value1], [key2, value2]]
        key % 2 === 1 ? res.push(...nums) : res.push(...nums.reverse())
    }
    return res
};

或者从上图可看出一些规律

第一趟:1 的坐标(0, 0)。x + y == 0;第二趟:2 的坐标(0, 1),4 的坐标(1, 0)。x + y == 1;第三趟:7 的坐标(2, 0), 5 的坐标(1, 1),3 的坐标(0, 2)。第三趟 x + y == 2;依此类推;每一趟对角线中元素的坐标(x, y)相加的和是递增的,从0开始递增到m+n-2(其中m为矩阵的宽度,n为矩阵的高度) 每一趟,如果是右上则是x+1和y-1,如果是左下则是x-1和y+1;

怎样确定每一趟初值:坐标和是从0开始,以题目示例中举例来说,当和为2时,遍历到元素3时,也就是坐标为(0,2)时,如何确定x,y的坐标, 应该尽量让y取最大,因为它是最右上角元素,接下来的方向需要左下;当和为3时,遍历到元素8时,也就是坐标(2,1),让x的坐标为3-1

怎样确定这一趟訪结束了,当然是超出矩阵索引位置

/**
 * @param {number[][]} mat
 * @return {number[]}
 */
var findDiagonalOrder = function (mat) {
  let nums = [];
  // 非空判定
  let m = mat.length;
  if (!m) return nums;
  let n = mat[0].length;
  if (!n) return nums;
  // 默认是右上
  let flag = true;
  // 为什么是<m + n - 1,举例来说1个3*3的矩阵,i的值最大是4 所以是小于m + n - 1=3+3-1
  for (let i = 0; i < m + n - 1; i++) {
    // m 和 n 的上界
    let limitM = flag ? m : n;
    let limitN = flag ? n : m;

    let x = i < limitM ? i : limitM - 1;
    let y = i - x;
    while (x >= 0 && y < limitN) {
      nums.push(flag ? mat[x][y] : mat[y][x]);
      x--;
      y++;
    }
    // 取相反,比方说右上变成左下,左下变成右上
    flag = !flag;
  }
  return nums;
};

四、总结

以上就是本道题的所有内容了,本系列会持续更,欢迎点赞、关注、收藏,另外如有其他的问题,欢迎下方留言给我,我会第一时间回复你,感谢~