对角线遍历

191 阅读1分钟

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

一、题目

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

二、题解

方法一

简单直接的就是根据题目的要求按顺序来遍历数组即可。可以根据题目的示例寻找规律,按对角线遍历的方向,要么是往右上角方向遍历下一个元素,要么就是往左下角遍历下一个元素。初始的就是从右上角方向遍历元素,然后遇到边界就换从左下角遍历元素,如此往复直到遍历结束。然后需要遍历的方向次数就是矩阵的两边边长相加再减一即m + n - 1次,所以对于每一次的对角线遍历,奇数次的时候方向是为往右上角的,偶数次的时候方法就是往左下角的。对于往右上角的方向遍历的话,下一个元素是在上一行下一列的位置,就是需要将行下标减一、列下标加一,需要注意不要超边界;而对于往左下角的方向遍历的话,下一个元素是在下一行上一列的位置,即需要将行下标加一、列下标减一,也需要注意边界。而每一次遇到边界的时候就需要转换方向,转换方向的时候就需要从另外一个起点开始按方向来遍历,当是奇数次方向的时候,遍历的起点就是最左下角;当是偶数次方向的时候,遍历的起点就是最右上角。

三、代码

方法一 Java代码

class Solution {
    public int[] findDiagonalOrder(int[][] mat) {
        int m = mat.length;
        int n = mat[0].length;
        int[] res = new int[m * n];
        int index = 0;
        for (int i = 0; i < m + n - 1; i++) {
            if (i % 2 == 1) {
                int y = Math.min(i, n - 1);
                int x = i - y;
                while (x < m && y >= 0) {
                    res[index++] = mat[x++][y--];
                }
            } else {
                int x = Math.min(i, m - 1);
                int y = i - x;
                while (y < n && x >= 0) {
                    res[index++] = mat[x--][y++];
                }
            }
        }
        return res;
    }
}

时间复杂度:O(n),需要遍历一次数组的所有元素。

空间复杂度:O(1),只需要使用常数的空间。