持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第20天,点击查看活动详情
题目描述
给你一个大小为 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
思路
首先我们可以想一下怎么遍历所有的对角线,可以分成2类:
- 起点在最左侧这一列
- 起点在最下面这一行 无论m和n哪个大,都可以分成上述2类,如下图所示
所以,我们通过遍历这个L行的边缘,就可以遍历这个矩形所有的对角线。
接下来我们想一下怎么遍历每条对角线内部的点。其实不难发现,在1条对角线上,相邻2个点始终满足
x2 = x1 - 1
y2 = y1 + 1
我们找到了起点之后,就可以使用这种方式去遍历对角线内部的点,直到x或者y超过矩形的范围。
当然,本题还有一个注意点是,对角线的顺序是按照一正一反类似斑马线交替的,所以我们可以使用一个变量reverse来保存当前的顺序,遍历下1条对角线的时候进行取反就好。
Java版本代码
class Solution {
public int[] findDiagonalOrder(int[][] mat) {
int m = mat.length;
int n = mat[0].length;
int[] arr = new int[m * n];
int index = 0;
// 是否需要反向的标识
boolean reverse = false;
// 起点在最左侧的对角线
for (int k = 0; k < m; k++) {
int x = k, y = 0;
List<Integer> line = new ArrayList<>();
while (x >= 0 && x < m && y >= 0 && y < n) {
line.add(mat[x--][y++]);
}
// 反向
if (reverse) {
Collections.reverse(line);
}
// 交替,1条正向,1条反向
reverse = !reverse;
for (int item : line) {
arr[index++] = item;
}
}
// 起点在最下方的对角线
for (int k = 1; k < n; k++) {
int x = m - 1, y = k;
List<Integer> line = new ArrayList<>();
while (x >= 0 && x < m && y >= 0 && y < n) {
line.add(mat[x--][y++]);
}
// 反向
if (reverse) {
Collections.reverse(line);
}
// 交替,1条正向,1条反向
reverse = !reverse;
for (int item : line) {
arr[index++] = item;
}
}
return arr;
}
}