对角线遍历
难度:
标签:
题目描述
给你一个大小为 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
代码结果
运行时间: 54 ms, 内存: 18.7 MB
/*
* 思路:
* 使用Java Stream API处理数据。
* 我们沿着对角线遍历矩阵,交替遍历向上和向下的对角线。
* 当总和为偶数时,我们向上遍历,当总和为奇数时,我们向下遍历。
* 遍历的过程中,我们将矩阵中的元素加入结果列表中。
*/
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.ArrayList;
import java.util.List;
public class DiagonalTraverseStream {
public int[] findDiagonalOrder(int[][] mat) {
int m = mat.length;
int n = mat[0].length;
List<Integer> result = new ArrayList<>();
for (int d = 0; d < m + n - 1; d++) {
final int sum = d;
List<Integer> diagonal = IntStream.range(0, m)
.filter(i -> sum - i >= 0 && sum - i < n)
.mapToObj(i -> mat[i][sum - i])
.collect(Collectors.toList());
if (d % 2 == 0) {
result.addAll(diagonal);
} else {
for (int i = diagonal.size() - 1; i >= 0; i--) {
result.add(diagonal.get(i));
}
}
}
return result.stream().mapToInt(i -> i).toArray();
}
}
解释
方法:
这个题解采用了分组和遍历的策略来实现对角线遍历。首先,根据矩阵元素的坐标(i, j),每个元素被分配到对应的对角线组里,这个组的索引是i+j。这意味着所有在同一个对角线上的元素会被放在同一个列表中。创建了一个列表数组ans来存储这些对角线组。然后,根据对角线的索引顺序,决定了遍历的方向:偶数索引的对角线从上到下遍历(逆序插入到结果列表中),奇数索引的对角线则从下到上遍历(顺序插入)。这样可以确保输出结果符合对角线遍历的要求。
时间复杂度:
O(m*n)
空间复杂度:
O(m*n)
代码细节讲解
🦆
请问在将每个元素按坐标和对角线的关系添加到对应列表时,为何选择了索引`i+j`作为对角线的标识?
▷🦆
在处理对角线元素的遍历方向时,代码中提到偶数索引对角线逆序添加,奇数索引顺序添加,这样的处理是基于什么考虑?
▷🦆
代码中使用了`ans[i+j].append(mat[i][j])`将元素添加到对应列表,这种添加方式是否考虑了对角线元素在原矩阵中的顺序?
▷🦆
在对ans列表进行遍历时,为什么每个对角线列表都需要分别处理逆序和顺序添加,这种方法相比于直接合并有什么优势?
▷