在问 · 算法题解

498. 对角线遍历

题目描述

输入 m x n 的矩阵 mat。

按对角线方向以之字形走遍整个矩阵:从左上角 mat[0][0] 出发,先沿右上方向走完第一条对角线,再换到下一条对角线沿左下方向走,此后方向在相邻对角线之间交替。这里的对角线指行号加列号相同的那些格子。

返回按这个顺序依次访问到的元素组成的数组。

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

解释:对角线依次读出 1、2,4、7,5,3、6,8、9,方向交替。

示例 2
输入:mat = [[1,2],[3,4]]
输出:[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

解题思路

同一条反对角线上的格子满足 i + j = d,d 从 0 到 m+n-2。d 为偶数时往右上走:i 从 min(d, m-1) 开始递减,列 j = d - i;d 为奇数时往左下走:j 从 min(d, n-1) 开始递减,行 i = d - j。循环条件同时检查另一坐标不越界。

为什么正确

处理第 d 条对角线时,res 中恰好是所有 i + j < d 的格子,按题目要求的顺序排列。

复杂度分析

时间 O(m·n),每个格子恰好访问一次;除结果外额外空间 O(1)。

易错点

起点不能直接取 i = d:当 d ≥ m 时行会越界,要取 min(d, m-1);同时循环条件还要检查 d - i < n,否则列会越界。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def findDiagonalOrder(self, mat: List[List[int]]) -> List[int]:
        m, n = len(mat), len(mat[0])
        res = []
        for d in range(m + n - 1):
            if d % 2 == 0:
                i = min(d, m - 1)
                while i >= 0 and d - i < n:
                    res.append(mat[i][d - i])
                    i -= 1
            else:
                j = min(d, n - 1)
                while j >= 0 and d - j < m:
                    res.append(mat[d - j][j])
                    j -= 1
        return res

载入编辑器,自己跑一遍 →

数学 专题的其他题目

查看 数学 全部题目 →