首先可以确定,每一条对角线其 i + j 的值都是定值,所以可以枚举这个定值;这个定值的范围显然是 [0, n - 1 + m - 1)
然后就是,如果对角线的值为偶数,那么就是从下往上遍历,否则就是从上往下;
对于从上往下的情况,最简单的就是其 i = 0,然后 i 一直递增即可,但显然在后半部分对角线,i 的初始值不是 0,应该是 (i + j) - (m - 1). 但实际上根本不需要区分前后半部分对角线,i 的初始值就是 max(0, (i + j) - (m - 1)).....然后就是 i 的最大值,很显然,后半部分对角线 i 的最大值为 n,而前半部分 i 的最大值为 (i + j).... 即 i 的上限为 min(i + j, n - 1)
对于从下往上的情况与上类似
class Solution { public: vector<int> findDiagonalOrder(vector<vector<int>>& mat) { if(mat.empty() || mat[0].empty()) return {}; int n = mat.size(), m = mat[0].size(); vector<int> ret; ret.reserve(n + m - 2); for(int i = 0; i < n + m - 1; ++ i) { // i 表示 原矩阵 行+列 的值, 因为每一条对角线 行+列 的固定 if(i & 1) { // 奇数, 从上至下 for(int j = max(0, i - (m - 1)); j < min(i + 1, n); ++ j) { // j 表示行 int k = i - j; // k 表示列 ret.emplace_back(mat[j][k]); } } else { // 偶数, 从下至上 for(int k = max(0, i - (n - 1)); k < min(i + 1, m); ++ k) { // k 表示列 int j = i - k; ret.emplace_back(mat[j][k]); } } } return ret; } };
但其实对于第二重 for 循环来说,可以不用算 for 的上界,因为如果 int k = i - j, k < 0 直接 break 即可。