一、题目
1、题目描述
给你一个大小为 m x n 的矩阵 mat ,请以对角线遍历的顺序,用一个数组返回这个矩阵中的所有元素。
2、基础框架
- C++版本给出的基础框架如下:
3、原题链接
https://leetcode.cn/problems/diagonal-traverse/
二、解题报告
1、思路分析
(
1
)
(1)
(1)对角线遍历和普通遍历的区别在于遍历指针的变化方式不同。
(
2
)
(2)
(2)可以观察,对角线遍历存在两个方向,所以要考虑方向变化,可以设置一个变量来控制方向。
(
3
)
(3)
(3)斜上方向,指针变化方式为i-1,j+1。斜下方向指针的变化方式为i+1,j-1。
(
4
)
(4)
(4)最大的难点在于边界条件的判断,二维数组可以看做矩形,有四条边,4个顶点,所以总共有8个边界,但由于遍历方向为2,4象限,所以只考虑2个顶点,所以总共需要考虑6个边界。
(
5
)
(5)
(5)第一行边界(除去顶点情况),当i<0时,发生越界,此时要调转方向,i+1,j不变。第一列边界(除去顶点情况),当j<0时,发生越界,此时要调转方向,i不变,j+1。最后一行边界(除去顶点情况),当i=m时,发生越界,此时要调转方向,i-1,j+2;最后一列边界(除去顶点情况),当j=n时,发生越界,此时要调转方向,i+2,j-1。右上顶点,当i<0并且j=n时,右上顶点越界,此时要调转方向,i+2,j-1。左下顶点,当j<0并且i=m时,左下顶点越界,此时要调转方向,i-1,j+2。
2、时间复杂度
时间复杂度O(mn),
空间复杂度O(mn)
3、代码详解
class Solution {
public:
vector<int> findDiagonalOrder(vector<vector<int>>& mat) {
vector<int> re;
int flag = 0;
int m = mat.size();
int n = mat[0].size();
int i = 0;
int j = 0;
while(1) {
re.push_back(mat[i][j]);
if (i == m-1 && j == n-1) break;
if (flag == 0) {
i = i - 1;
j = j + 1;
if (i < 0 && j >= n) {
i = i + 2;
j = j - 1;
flag = 1;
}
else if (i < 0 || j >= n) {
if (i < 0) {
i = i + 1;
}
if (j >= n) {
i = i + 2;
j = j - 1;
}
flag = 1;
}
}
else {
i = i + 1;
j = j - 1;
if (i >= m && j < 0) {
i = i - 1;
j = j + 2;
flag = 0;
}
else if (i >= m || j < 0) {
if (j < 0) {
j = j + 1;
}
if (i >= m) {
i = i - 1;
j = j + 2;
}
flag = 0;
}
}
}
return re;
}
};