既然已经说了这么多遍历,前中后,甚至还有垂序,我们再来看一道对角线遍历,不过不是二叉树的。
题目链接:
对角线遍历 - 力扣(LeetCode)leetcode-cn.com题目描述:
给定一个含有 M x N 个元素的矩阵(M 行,N 列),请以对角线遍历的顺序返回这个矩阵中的所有元素,对角线遍历如下图所示。
示例:
输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,4,7,5,3,6,8,9]
解释:
说明:
- 给定矩阵中的元素总数不会超过 100000 。
解题思路:
如上面的解释图所示,其实就是“之字形”的数组对角线遍历,和二叉树的“之字形”遍历一样,我们肯定需要有两个方向,一个往右上,一个往左下。在不考虑边界情况的条件下,前者是所在行数减一,列数加一,而后者正好相反。
而如果遇到遍历到边界的情况,其实也很简单。如果是遇到的是右上方方向超出边界,就让所在行数不变,而列数加一。如果是左下方方向超出边界,就让所在列数不变,而行数加一。
具体实现的时候,迭代递归都可以。我自己是用递归实现的。
代码如下:
class Solution {
public:
vector<int> findDiagonalOrder(vector<vector<int>>& matrix) {
vector<int> res;
if(matrix.empty()) return res;
int m = matrix.size(), n = matrix[0].size();
vector<pair<int, int>> dir({{-1, 1}, {1, -1}}); // 事先规定两个方向的移动参数
DFS(matrix, res, 0, 0, m, n, dir, 0);
return res;
}
private:
void DFS(vector<vector<int>>& matrix, vector<int>& res, int r, int c, int m, int n, vector<pair<int, int>>& dir, int d){
if(res.size() == m * n) return;
res.push_back(matrix[r][c]);
int R = r + dir[d].first;
int C = c + dir[d].second;
if(R < 0 || C < 0 || R >= m || C >= n){ // 如果超出边界
d = (d + 1) % 2; // 改变方向
if(R < 0 || R >= m) R = r, C = c + 1; // 对应右上方方向超出
if(C < 0 || C >= n) R = r + 1, C = c; // 对应左下方方向超出
}
DFS(matrix, res, R, C, m, n, dir, d);
}
};
如果有任何疑问,欢迎提出。如果有更好的解法,也欢迎告知。